Add mISDNuser to this project
This commit is contained in:
parent
7ebde07432
commit
4150cc3e67
|
@ -41,4 +41,5 @@ src/libosmocc/libosmocc.a
|
||||||
src/libsample/libsample.a
|
src/libsample/libsample.a
|
||||||
src/libtimer/libtimer.a
|
src/libtimer/libtimer.a
|
||||||
src/libmisdn/libmisdn.a
|
src/libmisdn/libmisdn.a
|
||||||
|
src/libmisdnuser/libmisdnuser.a
|
||||||
src/isdn/osmo-cc-misdn-endpoint
|
src/isdn/osmo-cc-misdn-endpoint
|
||||||
|
|
|
@ -88,6 +88,7 @@ AC_OUTPUT(
|
||||||
src/libosmocc/Makefile
|
src/libosmocc/Makefile
|
||||||
src/libg711/Makefile
|
src/libg711/Makefile
|
||||||
src/libmisdn/Makefile
|
src/libmisdn/Makefile
|
||||||
|
src/libmisdnuser/Makefile
|
||||||
src/isdn/Makefile
|
src/isdn/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
Makefile)
|
Makefile)
|
||||||
|
|
|
@ -9,5 +9,6 @@ SUBDIRS = \
|
||||||
libosmocc \
|
libosmocc \
|
||||||
libg711 \
|
libg711 \
|
||||||
libmisdn \
|
libmisdn \
|
||||||
|
libmisdnuser \
|
||||||
isdn
|
isdn
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
AM_CPPFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-array-bounds -Wno-sign-compare -g $(all_includes) -I$(srcdir)/include
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libmisdnuser.a
|
||||||
|
|
||||||
|
ASN1_SRC = asn1/asn1.c asn1/asn1_enc.c asn1/asn1_generic.c
|
||||||
|
|
||||||
|
SUPPSERV_SRC = suppserv/aoc.c suppserv/basic_service.c suppserv/component.c \
|
||||||
|
suppserv/diversion.c suppserv/address.c suppserv/ccbs.c \
|
||||||
|
suppserv/fac.c suppserv/ect.c suppserv/3pty.c
|
||||||
|
|
||||||
|
SUPPSERV_INC = include/ccbs.h include/diversion.h include/ect.h include/asn1.h \
|
||||||
|
include/3pty.h
|
||||||
|
|
||||||
|
|
||||||
|
MISC_SRC = misc/debug.c misc/fsm.c misc/mbuffer.c misc/mtimer.c
|
||||||
|
|
||||||
|
LAYER3_SRC = layer3/dss1net.c layer3/dss1user.c layer3/layer3.c layer3/mlayer3.c layer3/q931.c
|
||||||
|
|
||||||
|
INCLUDE_SRC = include/debug.h include/dss1.h include/fsm.h include/helper.h include/layer3.h \
|
||||||
|
include/mlist.h include/mtimer.h $(SUPPSERV_INC)
|
||||||
|
|
||||||
|
libmisdnuser_a_SOURCES = $(MISC_SRC) $(LAYER3_SRC) $(INCLUDE_SRC) $(ASN1_SRC) $(SUPPSERV_SRC)
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Basic ASN1 parser functions
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
|
||||||
|
int ParseTag(u_char * p, u_char * end, int *tag)
|
||||||
|
{
|
||||||
|
if (p >= end) {
|
||||||
|
eprint("ParseTag underflow %p/%p\n", p, end);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*tag = *p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseLen(u_char * p, u_char * end, int *len)
|
||||||
|
{
|
||||||
|
int l, i;
|
||||||
|
|
||||||
|
if (p >= end) {
|
||||||
|
eprint("ParseLen underflow %p/%p\n", p, end);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (*p == 0x80) { // indefinite
|
||||||
|
*len = -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!(*p & 0x80)) { // one byte
|
||||||
|
*len = *p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*len = 0;
|
||||||
|
l = *p & ~0x80;
|
||||||
|
p++;
|
||||||
|
if (p + l >= end) {
|
||||||
|
eprint("ParseLen underflow %p/%p\n", p, end);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < l; i++) {
|
||||||
|
*len = (*len << 8) + *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return l + 1;
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* Encode basic ASN1 elements
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int encodeLen_Long_u8(__u8 * dest, __u8 length)
|
||||||
|
{
|
||||||
|
dest[0] = 0x80 + ASN1_NUM_OCTETS_LONG_LENGTH_u8 - 1;
|
||||||
|
dest[1] = length;
|
||||||
|
return ASN1_NUM_OCTETS_LONG_LENGTH_u8;
|
||||||
|
} /* end encodeLen_Long_u8() */
|
||||||
|
|
||||||
|
int encodeLen_Long_u16(__u8 * dest, __u16 length)
|
||||||
|
{
|
||||||
|
dest[0] = 0x80 + ASN1_NUM_OCTETS_LONG_LENGTH_u16 - 1;
|
||||||
|
dest[1] = (length >> 8) & 0xFF;
|
||||||
|
dest[2] = length & 0xFF;
|
||||||
|
return ASN1_NUM_OCTETS_LONG_LENGTH_u16;
|
||||||
|
} /* end encodeLen_Long_u16() */
|
||||||
|
|
||||||
|
int encodeNull(__u8 * dest, __u8 tagType)
|
||||||
|
{
|
||||||
|
dest[0] = tagType;
|
||||||
|
dest[1] = 0; /* length */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encodeBoolean(__u8 * dest, __u8 tagType, __u32 i)
|
||||||
|
{
|
||||||
|
dest[0] = tagType;
|
||||||
|
dest[1] = 1; /* length */
|
||||||
|
dest[2] = i ? 1 : 0; /* value */
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encodeInt(__u8 * dest, __u8 tagType, __s32 i)
|
||||||
|
{
|
||||||
|
unsigned count;
|
||||||
|
__u32 test_mask;
|
||||||
|
__u32 value;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
dest[0] = tagType;
|
||||||
|
|
||||||
|
/* Find most significant octet of 32 bit integer that carries meaning. */
|
||||||
|
test_mask = 0xFF800000;
|
||||||
|
value = (__u32) i;
|
||||||
|
for (count = 4; --count;) {
|
||||||
|
if ((value & test_mask) != test_mask && (value & test_mask) != 0) {
|
||||||
|
/*
|
||||||
|
* The first 9 bits of a multiple octet integer is not
|
||||||
|
* all ones or zeroes.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
test_mask >>= 8;
|
||||||
|
} /* end for */
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
dest[1] = count + 1;
|
||||||
|
|
||||||
|
/* Store value */
|
||||||
|
p = &dest[2];
|
||||||
|
do {
|
||||||
|
value = (__u32) i;
|
||||||
|
value >>= (8 * count);
|
||||||
|
*p++ = value & 0xFF;
|
||||||
|
} while (count--);
|
||||||
|
|
||||||
|
return p - dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encodeEnum(__u8 * dest, __u8 tagType, __s32 i)
|
||||||
|
{
|
||||||
|
return encodeInt(dest, tagType, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use to encode the following string types:
|
||||||
|
* ASN1_TAG_OCTET_STRING
|
||||||
|
* ASN1_TAG_NUMERIC_STRING
|
||||||
|
* ASN1_TAG_PRINTABLE_STRING
|
||||||
|
* ASN1_TAG_IA5_STRING
|
||||||
|
*
|
||||||
|
* Note The string length MUST be less than 128 characters.
|
||||||
|
*/
|
||||||
|
static int encodeString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dest[0] = tagType;
|
||||||
|
|
||||||
|
/* Store value */
|
||||||
|
p = &dest[2];
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
*p++ = *str++;
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
dest[1] = p - &dest[2];
|
||||||
|
|
||||||
|
return p - dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encodeOctetString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
|
||||||
|
{
|
||||||
|
return encodeString(dest, tagType, str, len);
|
||||||
|
} /* end encodeOctetString() */
|
||||||
|
|
||||||
|
int encodeNumericString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
|
||||||
|
{
|
||||||
|
return encodeString(dest, tagType, str, len);
|
||||||
|
} /* end encodeNumericString() */
|
||||||
|
|
||||||
|
int encodePrintableString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
|
||||||
|
{
|
||||||
|
return encodeString(dest, tagType, str, len);
|
||||||
|
} /* end encodePrintableString() */
|
||||||
|
|
||||||
|
int encodeIA5String(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
|
||||||
|
{
|
||||||
|
return encodeString(dest, tagType, str, len);
|
||||||
|
} /* end encodeIA5String() */
|
||||||
|
|
||||||
|
int encodeOid(__u8 * dest, __u8 tagType, const struct asn1Oid *oid)
|
||||||
|
{
|
||||||
|
unsigned numValues;
|
||||||
|
unsigned count;
|
||||||
|
__u32 value;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
dest[0] = tagType;
|
||||||
|
|
||||||
|
/* For all OID subidentifer values */
|
||||||
|
p = &dest[2];
|
||||||
|
for (numValues = 0; numValues < oid->numValues; ++numValues) {
|
||||||
|
/*
|
||||||
|
* Count the number of 7 bit chunks that are needed
|
||||||
|
* to encode the integer.
|
||||||
|
*/
|
||||||
|
value = oid->value[numValues] >> 7;
|
||||||
|
for (count = 0; value; ++count) {
|
||||||
|
/* There are bits still set */
|
||||||
|
value >>= 7;
|
||||||
|
} /* end for */
|
||||||
|
|
||||||
|
/* Store OID subidentifier value */
|
||||||
|
do {
|
||||||
|
value = oid->value[numValues];
|
||||||
|
value >>= (7 * count);
|
||||||
|
*p++ = (value & 0x7F) | (count ? 0x80 : 0);
|
||||||
|
} while (count--);
|
||||||
|
} /* end for */
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
dest[1] = p - &dest[2];
|
||||||
|
|
||||||
|
return p - dest;
|
||||||
|
} /* end encodeOid() */
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* ASN1 parser for standard elements
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// general ASN.1
|
||||||
|
|
||||||
|
int ParseBoolean(struct asn1_parm *pc, u_char * p, u_char * end, int *i)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
*i = *p ? 1 : 0;
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> BOOL = %d %#x\n", *i, *i);
|
||||||
|
return end - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseNull(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseUInt(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *i)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
*i = 0;
|
||||||
|
while (len--) {
|
||||||
|
*i = (*i << 8) | *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseInt() */
|
||||||
|
|
||||||
|
static int ParseSInt(struct asn1_parm *pc, u_char * p, u_char * end, signed int *i)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
/* Read value as signed */
|
||||||
|
if (*p & 0x80) {
|
||||||
|
/* The value is negative */
|
||||||
|
*i = -1;
|
||||||
|
} else {
|
||||||
|
*i = 0;
|
||||||
|
}
|
||||||
|
while (len--) {
|
||||||
|
*i = (*i << 8) | *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseInt() */
|
||||||
|
|
||||||
|
int ParseUnsignedInteger(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *i)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
|
||||||
|
length = ParseUInt(pc, p, end, i);
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> INT = %d %#x\n", *i, *i);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseSignedInteger(struct asn1_parm *pc, u_char * p, u_char * end, signed int *i)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
|
||||||
|
length = ParseSInt(pc, p, end, i);
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> INT = %d %#x\n", *i, *i);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseEnum(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *i)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
|
||||||
|
length = ParseUInt(pc, p, end, i);
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> ENUM = %d %#x\n", *i, *i);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseIA5String(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1ParseString *str)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int numChars;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
/* We do not handle indefinite length strings */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str->maxSize < len + 1) {
|
||||||
|
numChars = str->maxSize - 1;
|
||||||
|
} else {
|
||||||
|
numChars = len;
|
||||||
|
}
|
||||||
|
len -= numChars;
|
||||||
|
str->length = numChars;
|
||||||
|
buf = str->buf;
|
||||||
|
while (numChars--)
|
||||||
|
*buf++ = *p++;
|
||||||
|
*buf = 0;
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> IA5 = %s\n", str->buf);
|
||||||
|
if (0 < len) {
|
||||||
|
wprint("Discard %d IA5 max %zd\n", len, str->maxSize);
|
||||||
|
/* Discard the remainder of the string. We have no room left. */
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseNumericString(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1ParseString *str)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int numChars;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
/* We do not handle indefinite length strings */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str->maxSize < len + 1) {
|
||||||
|
numChars = str->maxSize - 1;
|
||||||
|
} else {
|
||||||
|
numChars = len;
|
||||||
|
}
|
||||||
|
len -= numChars;
|
||||||
|
str->length = numChars;
|
||||||
|
buf = str->buf;
|
||||||
|
while (numChars--)
|
||||||
|
*buf++ = *p++;
|
||||||
|
*buf = 0;
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> NumStr = %s\n", str->buf);
|
||||||
|
if (0 < len) {
|
||||||
|
wprint("Discard %d NumStr max %zd\n", len, str->maxSize);
|
||||||
|
/* Discard the remainder of the string. We have no room left. */
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseOctetString(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1ParseString *str)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
/* We do not handle indefinite length strings */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (str->maxSize < len + 1) {
|
||||||
|
/*
|
||||||
|
* The octet string will not fit in the available buffer
|
||||||
|
* and truncating it is not a good idea in all cases.
|
||||||
|
*/
|
||||||
|
eprint("OctetString does not fit %d max %zd\n", len, str->maxSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
str->length = len;
|
||||||
|
buf = str->buf;
|
||||||
|
while (len--)
|
||||||
|
*buf++ = *p++;
|
||||||
|
*buf = 0;
|
||||||
|
if (DBGM_ASN1_DEC & mI_debug_mask) {
|
||||||
|
char *tmp = malloc((3 * len) + 1);
|
||||||
|
|
||||||
|
if (tmp) {
|
||||||
|
mi_shexprint(tmp, p, len);
|
||||||
|
dprint(DBGM_ASN1_DEC, " DEBUG> Octets = %s\n", tmp);
|
||||||
|
free(tmp);
|
||||||
|
} else
|
||||||
|
eprint("MALLOC for %d bytes failed\n", (3 * len) + 1);
|
||||||
|
}
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseOid(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1Oid *oid)
|
||||||
|
{
|
||||||
|
int numValues;
|
||||||
|
int value;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
numValues = 0;
|
||||||
|
while (len) {
|
||||||
|
value = 0;
|
||||||
|
for (;;) {
|
||||||
|
--len;
|
||||||
|
value = (value << 7) | (*p & 0x7F);
|
||||||
|
if (!(*p++ & 0x80)) {
|
||||||
|
/* Last octet in the OID subidentifier value */
|
||||||
|
if (numValues < sizeof(oid->value) / sizeof(oid->value[0])) {
|
||||||
|
oid->value[numValues] = value;
|
||||||
|
} else {
|
||||||
|
dprint(DBGM_ASN1_WARN, "Too many OID subidentifier %d\n", value);
|
||||||
|
}
|
||||||
|
++numValues;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!len) {
|
||||||
|
oid->numValues = 0;
|
||||||
|
wprint("Last OID subidentifier value (%d) not terminated!\n", value);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} /* end for */
|
||||||
|
} /* end while */
|
||||||
|
|
||||||
|
if (numValues <= sizeof(oid->value) / sizeof(oid->value[0])) {
|
||||||
|
oid->numValues = numValues;
|
||||||
|
for (numValues = 0; numValues < oid->numValues; numValues++)
|
||||||
|
dprint(DBGM_ASN1_DEC, "OID->value[%d] = %d\n", numValues, oid->value[numValues]);
|
||||||
|
return p - beg;
|
||||||
|
} else {
|
||||||
|
/* Need to increase the size of the OID subidentifier list. */
|
||||||
|
wprint("Too many OID values (%d)!\n", numValues);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Three Party (3PTY) Supplementary Services ETS 300 188-2
|
||||||
|
*
|
||||||
|
* 3PTY Facility ie encode/decode header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASN1_3PTY_H
|
||||||
|
#define __ASN1_3PTY_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int encodeFacBegin3PTY(__u8 * Dest, const struct asn1_parm *pc, const void *unused);
|
||||||
|
int encodeFacEnd3PTY(__u8 * Dest, const struct asn1_parm *pc, const void *unused);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __ASN1_3PTY_H */
|
||||||
|
/* ------------------------------------------------------------------- *//* end asn1_3pty.h */
|
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Abstract Syntax Notation.1 (ASN.1) ITU-T X.208
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASN1_H__
|
||||||
|
#define __ASN1_H__
|
||||||
|
|
||||||
|
#include <mISDN/suppserv.h>
|
||||||
|
#include <asm/types.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int ParseTag(u_char * p, u_char * end, int *tag);
|
||||||
|
int ParseLen(u_char * p, u_char * end, int *len);
|
||||||
|
|
||||||
|
#define ASN1_TAG_BOOLEAN 1
|
||||||
|
#define ASN1_TAG_INTEGER 2
|
||||||
|
#define ASN1_TAG_BIT_STRING 3
|
||||||
|
#define ASN1_TAG_OCTET_STRING 4
|
||||||
|
#define ASN1_TAG_NULL 5
|
||||||
|
#define ASN1_TAG_OBJECT_IDENTIFIER 6
|
||||||
|
#define ASN1_TAG_ENUM 10
|
||||||
|
#define ASN1_TAG_SEQUENCE (ASN1_TAG_CONSTRUCTED | 16)
|
||||||
|
#define ASN1_TAG_SET (ASN1_TAG_CONSTRUCTED | 17)
|
||||||
|
#define ASN1_TAG_NUMERIC_STRING 18
|
||||||
|
#define ASN1_TAG_PRINTABLE_STRING 19
|
||||||
|
#define ASN1_TAG_IA5_STRING 22
|
||||||
|
#define ASN1_TAG_UTC_TIME 23
|
||||||
|
|
||||||
|
#define ASN1_TAG_CONSTRUCTED 0x20
|
||||||
|
|
||||||
|
#define ASN1_TAG_TYPE_MASK 0xC0
|
||||||
|
#define ASN1_TAG_UNIVERSAL 0x00
|
||||||
|
#define ASN1_TAG_APPLICATION_WIDE 0x40
|
||||||
|
#define ASN1_TAG_CONTEXT_SPECIFIC 0x80
|
||||||
|
#define ASN1_TAG_PRIVATE 0xC0
|
||||||
|
|
||||||
|
#define ASN1_TAG_EXPLICIT 0x100
|
||||||
|
#define ASN1_TAG_OPT 0x200
|
||||||
|
#define ASN1_NOT_TAGGED 0x400
|
||||||
|
|
||||||
|
#define CallASN1(ret, p, end, todo) \
|
||||||
|
do { \
|
||||||
|
ret = todo; \
|
||||||
|
if (ret < 0) { \
|
||||||
|
eprint("CallASN1 internal error\n"); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
p += ret; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* INIT must be placed after the last variable declared */
|
||||||
|
#define INIT \
|
||||||
|
int tag, len; \
|
||||||
|
int ret; \
|
||||||
|
u_char *beg __attribute__((unused)); \
|
||||||
|
\
|
||||||
|
beg = p; \
|
||||||
|
CallASN1(ret, p, end, ParseTag(p, end, &tag)); \
|
||||||
|
CallASN1(ret, p, end, ParseLen(p, end, &len)); \
|
||||||
|
if (len >= 0) { \
|
||||||
|
if (p + len > end) { \
|
||||||
|
eprint("ASN1 parser underflow %p/%p in %s\n", p + len, end, __func__); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
dprint(DBGM_ASN1_DEC, "Start p=%p end=%p-->%p len=%d\n", p, end, p + len, len); \
|
||||||
|
end = p + len; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define XSEQUENCE_1(todo, act_tag, the_tag, arg1) \
|
||||||
|
do { \
|
||||||
|
if (p < end) { \
|
||||||
|
if (((the_tag) & ~ASN1_TAG_OPT) == ASN1_NOT_TAGGED) { \
|
||||||
|
if (((act_tag) == ASN1_NOT_TAGGED) || ((u_char) (act_tag) == *p)) { \
|
||||||
|
CallASN1(ret, p, end, todo(pc, p, end, arg1)); \
|
||||||
|
} else { \
|
||||||
|
if (!((the_tag) & ASN1_TAG_OPT)) { \
|
||||||
|
eprint("ASN1 XSEQUENCE_1 internal error 1\n"); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} else if ((the_tag) & ASN1_TAG_EXPLICIT) { \
|
||||||
|
/* EXPLICIT tags are always constructed */ \
|
||||||
|
if ((u_char) (((the_tag) & 0xff) | (((act_tag) & ASN1_TAG_TYPE_MASK) | ASN1_TAG_CONSTRUCTED)) == *p) { \
|
||||||
|
int xtag, xlen; \
|
||||||
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag)); \
|
||||||
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen)); \
|
||||||
|
CallASN1(ret, p, end, todo(pc, p, end, arg1)); \
|
||||||
|
} else { \
|
||||||
|
if (!((the_tag) & ASN1_TAG_OPT)) { \
|
||||||
|
eprint("ASN1 XSEQUENCE_1 internal error 2\n"); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} else { /* IMPLICIT */ \
|
||||||
|
if ((u_char) (((the_tag) & 0xff) | ((act_tag) & (ASN1_TAG_TYPE_MASK | ASN1_TAG_CONSTRUCTED))) == *p) { \
|
||||||
|
CallASN1(ret, p, end, todo(pc, p, end, arg1)); \
|
||||||
|
} else { \
|
||||||
|
if (!((the_tag) & ASN1_TAG_OPT)) { \
|
||||||
|
eprint("ASN1 XSEQUENCE_1 internal error 3\n"); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
if (!((the_tag) & ASN1_TAG_OPT)) { \
|
||||||
|
eprint("ASN1 XSEQUENCE_1 internal error 4\n"); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define XSEQUENCE_OPT_1(todo, act_tag, the_tag, arg1) \
|
||||||
|
XSEQUENCE_1(todo, act_tag, (the_tag | ASN1_TAG_OPT), arg1)
|
||||||
|
|
||||||
|
#define XSEQUENCE(todo, act_tag, the_tag) XSEQUENCE_1(todo, act_tag, the_tag, -1)
|
||||||
|
#define XSEQUENCE_OPT(todo, act_tag, the_tag) XSEQUENCE_OPT_1(todo, act_tag, the_tag, -1)
|
||||||
|
|
||||||
|
#define XCHOICE_1(todo, act_tag, the_tag, arg1) \
|
||||||
|
do { \
|
||||||
|
if ((act_tag) == ASN1_NOT_TAGGED) { \
|
||||||
|
return todo(pc, beg, end, arg1); \
|
||||||
|
} else if ((the_tag) == ASN1_NOT_TAGGED) { \
|
||||||
|
if ((act_tag) == tag) { \
|
||||||
|
return todo(pc, beg, end, arg1); \
|
||||||
|
} \
|
||||||
|
} else if ((act_tag) & ASN1_TAG_EXPLICIT) { \
|
||||||
|
/* EXPLICIT tags are always constructed */ \
|
||||||
|
if (((the_tag) | (((act_tag) & ASN1_TAG_TYPE_MASK) | ASN1_TAG_CONSTRUCTED)) == tag) { \
|
||||||
|
return todo(pc, p, end, arg1); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
if (((the_tag) | ((act_tag) & (ASN1_TAG_TYPE_MASK | ASN1_TAG_CONSTRUCTED))) == tag) { \
|
||||||
|
return todo(pc, beg, end, arg1); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define XCHOICE(todo, act_tag, the_tag) XCHOICE_1(todo, act_tag, the_tag, -1)
|
||||||
|
|
||||||
|
#define XCHOICE_DEFAULT \
|
||||||
|
do { \
|
||||||
|
eprint("ASN1 XCHOICE_DEFAULT internal error in %s\n", __func__); \
|
||||||
|
return -1; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CHECK_P \
|
||||||
|
do { \
|
||||||
|
if (p >= end) { \
|
||||||
|
eprint("ASN1 parser underflow %p/%p in %s\n", p, end, __func__); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
const struct asn1OidConvert *FindOidByOidValue(int length, const __u16 oidValues[]);
|
||||||
|
const struct asn1OidConvert *FindOidByEnum(__u16 value);
|
||||||
|
__u16 ConvertOidToEnum(const struct asn1Oid *oid, __u16 errorValue);
|
||||||
|
int ConvertEnumToOid(struct asn1Oid *oid, __u16 enumValue);
|
||||||
|
#define IsEnumOid(enumValue) \
|
||||||
|
((FAC_OID_BASE(1) <= (enumValue) \
|
||||||
|
&& (enumValue) < FAC_OID_BASE(FacOIDBase_Last)) ? 1 : 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** ASN.1 Encoding
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Facility-Information-Element-Components prototypes */
|
||||||
|
enum asn1ComponentTag {
|
||||||
|
asn1ComponentTag_Invoke = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1,
|
||||||
|
asn1ComponentTag_Result = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2,
|
||||||
|
asn1ComponentTag_Error = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3,
|
||||||
|
asn1ComponentTag_Reject = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 4,
|
||||||
|
};
|
||||||
|
__u8 *encodeComponent_Head(__u8 * p, enum asn1ComponentTag componentTag);
|
||||||
|
__u8 *encodeComponent_Head_Long_u8(__u8 * p, enum asn1ComponentTag componentTag);
|
||||||
|
int encodeComponent_Length(__u8 * msg, __u8 * end);
|
||||||
|
int encodeComponent_Length_Long_u8(__u8 * msg, __u8 * p);
|
||||||
|
|
||||||
|
__u8 *encodeComponentInvoke_Head(__u8 * Dest, int InvokeID, enum Operation OperationValue);
|
||||||
|
__u8 *encodeComponentInvoke_Head_Long_u8(__u8 * Dest, int InvokeID, enum Operation OperationValue);
|
||||||
|
|
||||||
|
int encodeOperationValue(__u8 * dest, int operationValue);
|
||||||
|
int encodeErrorValue(__u8 * dest, int errorValue);
|
||||||
|
|
||||||
|
/* Primitive ASN.1 prototypes */
|
||||||
|
#define ASN1_NUM_OCTETS_LONG_LENGTH_u8 2
|
||||||
|
#define ASN1_NUM_OCTETS_LONG_LENGTH_u16 3
|
||||||
|
int encodeLen_Long_u8(__u8 * dest, __u8 length);
|
||||||
|
int encodeLen_Long_u16(__u8 * dest, __u16 length);
|
||||||
|
|
||||||
|
int encodeNull(__u8 * dest, __u8 tagType);
|
||||||
|
int encodeBoolean(__u8 * dest, __u8 tagType, __u32 i);
|
||||||
|
int encodeInt(__u8 * dest, __u8 tagType, __s32 i);
|
||||||
|
int encodeEnum(__u8 * dest, __u8 tagType, __s32 i);
|
||||||
|
int encodeOctetString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len);
|
||||||
|
int encodeNumericString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len);
|
||||||
|
int encodePrintableString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len);
|
||||||
|
int encodeIA5String(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len);
|
||||||
|
int encodeOid(__u8 * dest, __u8 tagType, const struct asn1Oid *oid);
|
||||||
|
|
||||||
|
/* Addressing-Data-Elements prototypes */
|
||||||
|
int encodePartyNumber_Full(__u8 * Dest, const struct FacPartyNumber *PartyNumber);
|
||||||
|
int encodePartySubaddress_Full(__u8 * Dest, const struct FacPartySubaddress *PartySubaddress);
|
||||||
|
int encodeAddress_Full(__u8 * Dest, const struct FacAddress *Address);
|
||||||
|
int encodePresentedNumberUnscreened_Full(__u8 * Dest, const struct FacPresentedNumberUnscreened *Presented);
|
||||||
|
int encodePresentedAddressScreened_Full(__u8 * Dest, const struct FacPresentedAddressScreened *Presented);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** ASN.1 Parsing
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Facility-Information-Element-Components prototypes */
|
||||||
|
int ParseComponent(struct asn1_parm *parm, u_char * p, u_char * end);
|
||||||
|
|
||||||
|
/* Primitive ASN.1 prototypes */
|
||||||
|
int ParseBoolean(struct asn1_parm *pc, u_char * p, u_char * end, int *i);
|
||||||
|
int ParseNull(struct asn1_parm *pc, u_char * p, u_char * end, int dummy);
|
||||||
|
int ParseUnsignedInteger(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *i);
|
||||||
|
int ParseSignedInteger(struct asn1_parm *pc, u_char * p, u_char * end, signed int *i);
|
||||||
|
int ParseEnum(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *i);
|
||||||
|
|
||||||
|
struct asn1ParseString {
|
||||||
|
char *buf; /* Where to put the parsed string characters */
|
||||||
|
size_t maxSize; /* sizeof string buffer (Including an ASCIIz terminator) */
|
||||||
|
size_t length; /* length of string put into the string buffer (Without the terminator) */
|
||||||
|
};
|
||||||
|
int ParseIA5String(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1ParseString *str);
|
||||||
|
int ParseNumericString(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1ParseString *str);
|
||||||
|
int ParseOctetString(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1ParseString *str);
|
||||||
|
int ParseOid(struct asn1_parm *pc, u_char * p, u_char * end, struct asn1Oid *oid);
|
||||||
|
|
||||||
|
/* Addressing-Data-Elements prototypes */
|
||||||
|
int ParsePartyNumber_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartyNumber *PartyNumber);
|
||||||
|
int ParsePartySubaddress_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartySubaddress *PartySubaddress);
|
||||||
|
int ParseAddress_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAddress *Address);
|
||||||
|
int ParsePresentedNumberUnscreened_Full(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacPresentedNumberUnscreened *Presented);
|
||||||
|
int ParsePresentedAddressScreened_Full(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacPresentedAddressScreened *Presented);
|
||||||
|
|
||||||
|
/* Advice Of Charge (AOC) prototypes */
|
||||||
|
int ParseAOCECurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur);
|
||||||
|
int ParseAOCDChargingUnit(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu);
|
||||||
|
int ParseAOCDCurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur);
|
||||||
|
int ParseAOCDCurrencyInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur);
|
||||||
|
int ParseAOCDChargingUnitInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu);
|
||||||
|
int ParseRecordedCurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur);
|
||||||
|
int ParseRecordedUnitsList(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *recordedUnits);
|
||||||
|
int ParseTypeOfChargingInfo(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *typeOfChargingInfo);
|
||||||
|
int ParseRecordedUnits(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *recordedUnits);
|
||||||
|
int ParseAOCDBillingId(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *billingId);
|
||||||
|
int ParseAOCECurrencyInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur);
|
||||||
|
int ParseAOCEChargingUnit(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu);
|
||||||
|
int ParseAOCEChargingUnitInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu);
|
||||||
|
int ParseAOCEBillingId(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *billingId);
|
||||||
|
int ParseCurrency(struct asn1_parm *pc, u_char * p, u_char * end, char *currency);
|
||||||
|
int ParseAmount(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur);
|
||||||
|
int ParseCurrencyAmount(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *currencyAmount);
|
||||||
|
int ParseMultiplier(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *multiplier);
|
||||||
|
int ParseTypeOfUnit(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *typeOfUnit);
|
||||||
|
int ParseNumberOfUnits(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *numberOfUnits);
|
||||||
|
int ParseChargingAssociation(struct asn1_parm *pc, u_char * p, u_char * end, struct ChargingAssociation *chargeAssoc);
|
||||||
|
int ParseChargeIdentifier(struct asn1_parm *pc, u_char * p, u_char * end, int *chargeIdentifier);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __ASN1_H__ */
|
||||||
|
/* ------------------------------------------------------------------- *//* end asn1.h */
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* CCBS Supplementary Services ETS 300 359-1
|
||||||
|
* CCNR Supplementary Services ETS 301 065-1
|
||||||
|
*
|
||||||
|
* Generic functional protocol for the support of supplementary services ETS 300 196-1
|
||||||
|
*
|
||||||
|
* CCBS/CCNR Facility ie encode/decode header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASN1_CCBS_H
|
||||||
|
#define __ASN1_CCBS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int encodeFacStatusRequest(__u8 * Dest, const struct asn1_parm *pc, const struct FacStatusRequest *StatusRequest);
|
||||||
|
int ParseStatusRequest(struct asn1_parm *pc, u_char * p, u_char * end, struct FacStatusRequest *StatusRequest);
|
||||||
|
int ParseStatusRequest_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacStatusRequest_RES *StatusRequest);
|
||||||
|
|
||||||
|
int encodeFacCallInfoRetain(__u8 * Dest, const struct asn1_parm *pc, const struct FacCallInfoRetain *CallInfoRetain);
|
||||||
|
int ParseCallInfoRetain(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCallInfoRetain *CallInfoRetain);
|
||||||
|
|
||||||
|
int encodeFacEraseCallLinkageID(__u8 * Dest, const struct asn1_parm *pc, const struct FacEraseCallLinkageID *EraseCallLinkageID);
|
||||||
|
int ParseEraseCallLinkageID(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacEraseCallLinkageID *EraseCallLinkageID);
|
||||||
|
|
||||||
|
int encodeFacCCBSDeactivate(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSDeactivate *CCBSDeactivate);
|
||||||
|
int ParseCCBSDeactivate(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSDeactivate *CCBSDeactivate);
|
||||||
|
|
||||||
|
int encodeFacCCBSErase(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSErase *CCBSErase);
|
||||||
|
int ParseCCBSErase(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSErase *CCBSErase);
|
||||||
|
|
||||||
|
int encodeFacCCBSRemoteUserFree(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSRemoteUserFree *CCBSRemoteUserFree);
|
||||||
|
int ParseCCBSRemoteUserFree(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSRemoteUserFree *CCBSRemoteUserFree);
|
||||||
|
|
||||||
|
int encodeFacCCBSCall(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSCall *CCBSCall);
|
||||||
|
int ParseCCBSCall(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSCall *CCBSCall);
|
||||||
|
|
||||||
|
int encodeFacCCBSBFree(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSBFree *CCBSBFree);
|
||||||
|
int ParseCCBSBFree(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSBFree *CCBSBFree);
|
||||||
|
|
||||||
|
int encodeFacCCBSStopAlerting(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSStopAlerting *CCBSStopAlerting);
|
||||||
|
int ParseCCBSStopAlerting(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSStopAlerting *CCBSStopAlerting);
|
||||||
|
|
||||||
|
int encodeFacCCBSStatusRequest(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSStatusRequest *CCBSStatusRequest);
|
||||||
|
int ParseCCBSStatusRequest(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSStatusRequest *CCBSStatusRequest);
|
||||||
|
int ParseCCBSStatusRequest_RES(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSStatusRequest_RES *CCBSStatusRequest);
|
||||||
|
|
||||||
|
int encodeFacCCBSRequest(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSRequest *CCBSRequest);
|
||||||
|
int encodeFacCCNRRequest(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSRequest *CCNRRequest);
|
||||||
|
int ParseCCBSRequest(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSRequest *CCBSRequest);
|
||||||
|
int ParseCCNRRequest(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSRequest *CCNRRequest);
|
||||||
|
int ParseCCBSRequest_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSRequest_RES *CCBSRequest);
|
||||||
|
int ParseCCNRRequest_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBSRequest_RES *CCNRRequest);
|
||||||
|
|
||||||
|
int encodeFacCCBSInterrogate(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSInterrogate *CCBSInterrogate);
|
||||||
|
int encodeFacCCNRInterrogate(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBSInterrogate *CCNRInterrogate);
|
||||||
|
int ParseCCBSInterrogate(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSInterrogate *CCBSInterrogate);
|
||||||
|
int ParseCCNRInterrogate(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSInterrogate *CCNRInterrogate);
|
||||||
|
int ParseCCBSInterrogate_RES(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSInterrogate_RES *CCBSInterrogate);
|
||||||
|
int ParseCCNRInterrogate_RES(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacCCBSInterrogate_RES *CCNRInterrogate);
|
||||||
|
|
||||||
|
int encodeFacCCBS_T_Call(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
int encodeFacCCBS_T_Suspend(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
int encodeFacCCBS_T_Resume(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
int encodeFacCCBS_T_RemoteUserFree(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
int encodeFacCCBS_T_Available(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
|
||||||
|
int encodeFacCCBS_T_Request(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBS_T_Request *CCBS_T_Request);
|
||||||
|
int encodeFacCCNR_T_Request(__u8 * Dest, const struct asn1_parm *pc, const struct FacCCBS_T_Request *CCNR_T_Request);
|
||||||
|
int ParseCCBS_T_Request(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBS_T_Request *CCBS_T_Request);
|
||||||
|
int ParseCCNR_T_Request(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBS_T_Request *CCNR_T_Request);
|
||||||
|
int ParseCCBS_T_Request_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBS_T_Request_RES *CCBS_T_Request);
|
||||||
|
int ParseCCNR_T_Request_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCCBS_T_Request_RES *CCNR_T_Request);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __ASN1_CCBS_H */
|
||||||
|
/* ------------------------------------------------------------------- *//* end asn1_ccbs.h */
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* debug.h
|
||||||
|
*
|
||||||
|
* Basic Layer3 functions
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
* Copyright 2009, 2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef ISDN_DEBUG_H
|
||||||
|
#define ISDN_DEBUG_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mISDN/mISDNcompat.h>
|
||||||
|
|
||||||
|
#define L3_DEB_WARN 0x00000001
|
||||||
|
#define L3_DEB_PROTERR 0x00000002
|
||||||
|
#define L3_DEB_STATE 0x00000004
|
||||||
|
#define L3_DEB_PROC 0x00000008
|
||||||
|
#define L3_DEB_CHECK 0x00000010
|
||||||
|
#define DBGM_L3 0x00000040
|
||||||
|
#define DBGM_L3DATA 0x00000080
|
||||||
|
#define DBGM_L3BUFFER 0x00000100
|
||||||
|
#define DBGM_L2 0x00000200
|
||||||
|
#define DBGM_L2_STATE 0x00000400
|
||||||
|
#define DBGM_ASN1_WARN 0x00010000
|
||||||
|
#define DBGM_ASN1_ENC 0x00020000
|
||||||
|
#define DBGM_ASN1_DEC 0x00040000
|
||||||
|
#define DBGM_ASN1_DATA 0x00080000
|
||||||
|
#define DBGM_ALL 0xffffffff
|
||||||
|
|
||||||
|
extern unsigned int mI_debug_mask;
|
||||||
|
|
||||||
|
#define mi_thread_create(a, b, c, d) _mi_thread_create(a, b, c, d, __FILE__, __PRETTY_FUNCTION__, __LINE__, #c)
|
||||||
|
extern int _mi_thread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *),
|
||||||
|
void *arg, const char *file, const char *caller, int line, const char *start_fn);
|
||||||
|
|
||||||
|
|
||||||
|
#define eprint(fmt, ...) mi_printf(__FILE__, __LINE__, __PRETTY_FUNCTION__, 1, fmt, ##__VA_ARGS__)
|
||||||
|
#define wprint(fmt, ...) mi_printf(__FILE__, __LINE__, __PRETTY_FUNCTION__, 2, fmt, ##__VA_ARGS__)
|
||||||
|
#define iprint(fmt, ...) mi_printf(__FILE__, __LINE__, __PRETTY_FUNCTION__, 3, fmt, ##__VA_ARGS__)
|
||||||
|
#define dprint(m, fmt, ...) do { if (m & mI_debug_mask) mi_printf(__FILE__, __LINE__, __PRETTY_FUNCTION__, 4, fmt, ##__VA_ARGS__);} while(0)
|
||||||
|
|
||||||
|
extern int mi_printf(const char *file, int line, const char *func, int lev, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
|
||||||
|
|
||||||
|
#define dhexprint(m, h, d, l) do { if (m & mI_debug_mask) mi_dhexprint(__FILE__, __LINE__, __PRETTY_FUNCTION__, h, d, l);} while(0)
|
||||||
|
|
||||||
|
extern void mi_dhexprint(const char *file, int line, const char *func, const char *head, unsigned char *buf, int len);
|
||||||
|
extern void mi_shexprint(char *dest, unsigned char *buf, int len);
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
extern void *__mi_alloc(size_t size, const char *file, int lineno, const char *func);
|
||||||
|
extern void *__mi_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func);
|
||||||
|
extern void __mi_free(void *ptr, const char *file, int lineno, const char *func);
|
||||||
|
extern void __mi_reuse(void *ptr, const char *file, int lineno, const char *func);
|
||||||
|
|
||||||
|
#undef malloc
|
||||||
|
#undef calloc
|
||||||
|
#undef free
|
||||||
|
|
||||||
|
#define malloc(s) __mi_alloc(s, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
#define calloc(n, s) __mi_calloc(n, s, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
#define free(p) __mi_free(p, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Diversion Supplementary Services ETS 300 207-1 Table 3
|
||||||
|
*
|
||||||
|
* Diversion Facility ie encode/decode header
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASN1_DIVERSION_H__
|
||||||
|
#define __ASN1_DIVERSION_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int encodeFacActivationDiversion(__u8 * Dest, const struct asn1_parm *pc, const struct FacActivationDiversion *ActivationDiversion);
|
||||||
|
int ParseActivationDiversion(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacActivationDiversion *ActivationDiversion);
|
||||||
|
|
||||||
|
int encodeFacDeactivationDiversion(__u8 * Dest, const struct asn1_parm *pc, const struct FacDeactivationDiversion *DeactivationDiversion);
|
||||||
|
int ParseDeactivationDiversion(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacDeactivationDiversion *DeactivationDiversion);
|
||||||
|
|
||||||
|
int encodeFacActivationStatusNotificationDiv(__u8 * Dest, const struct asn1_parm *pc,
|
||||||
|
const struct FacActivationStatusNotificationDiv
|
||||||
|
*ActivationStatusNotificationDiv);
|
||||||
|
int ParseActivationStatusNotificationDiv(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacActivationStatusNotificationDiv *ActivationStatusNotificationDiv);
|
||||||
|
|
||||||
|
int encodeFacDeactivationStatusNotificationDiv(__u8 * Dest, const struct asn1_parm *pc,
|
||||||
|
const struct FacDeactivationStatusNotificationDiv
|
||||||
|
*DeactivationStatusNotificationDiv);
|
||||||
|
int ParseDeactivationStatusNotificationDiv(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacDeactivationStatusNotificationDiv
|
||||||
|
*DeactivationStatusNotificationDiv);
|
||||||
|
|
||||||
|
int encodeFacInterrogationDiversion(__u8 * Dest, const struct asn1_parm *pc, const struct FacInterrogationDiversion *InterrogationDiversion);
|
||||||
|
int ParseInterrogationDiversion(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacInterrogationDiversion *InterrogationDiversion);
|
||||||
|
#define ParseInterrogationDiversion_RES ParseIntResultList
|
||||||
|
int ParseIntResultList(struct asn1_parm *pc, u_char * p, u_char * end, struct FacForwardingList *IntResultList);
|
||||||
|
|
||||||
|
int encodeFacDiversionInformation(__u8 * Dest, const struct asn1_parm *pc, const struct FacDiversionInformation *DiversionInformation);
|
||||||
|
int ParseDiversionInformation(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacDiversionInformation *DiversionInformation);
|
||||||
|
|
||||||
|
int encodeFacCallDeflection(__u8 * Dest, const struct asn1_parm *pc, const struct FacCallDeflection *CallDeflection);
|
||||||
|
int ParseCallDeflection(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCallDeflection *CallDeflection);
|
||||||
|
|
||||||
|
int encodeFacCallRerouteing(__u8 * Dest, const struct asn1_parm *pc, const struct FacCallRerouteing *CallRerouteing);
|
||||||
|
int ParseCallRerouteing(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCallRerouteing *CallRerouteing);
|
||||||
|
|
||||||
|
int encodeFacInterrogateServedUserNumbers(__u8 * Dest, const struct asn1_parm *pc,
|
||||||
|
const struct FacServedUserNumberList *InterrogateServedUserNumbers);
|
||||||
|
#define ParseInterrogateServedUserNumbers_RES ParseServedUserNumberList
|
||||||
|
int ParseServedUserNumberList(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacServedUserNumberList *ServedUserNumberList);
|
||||||
|
|
||||||
|
int encodeFacDivertingLegInformation1(__u8 * Dest, const struct asn1_parm *pc, const struct FacDivertingLegInformation1 *DivertingLegInformation1);
|
||||||
|
int ParseDivertingLegInformation1(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacDivertingLegInformation1 *DivertingLegInformation1);
|
||||||
|
|
||||||
|
int encodeFacDivertingLegInformation2(__u8 * Dest, const struct asn1_parm *pc, const struct FacDivertingLegInformation2 *DivertingLegInformation2);
|
||||||
|
int ParseDivertingLegInformation2(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacDivertingLegInformation2 *DivertingLegInformation2);
|
||||||
|
|
||||||
|
int encodeFacDivertingLegInformation3(__u8 * Dest, const struct asn1_parm *pc, const struct FacDivertingLegInformation3 *DivertingLegInformation3);
|
||||||
|
int ParseDivertingLegInformation3(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacDivertingLegInformation3 *DivertingLegInformation3);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __ASN1_DIVERSION_H__ */
|
||||||
|
/* ------------------------------------------------------------------- *//* end asn1_diversion.h */
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* dss1.h
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DSS1_H
|
||||||
|
#define DSS1_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer values
|
||||||
|
*/
|
||||||
|
#define T302 15000
|
||||||
|
#define T303 4000
|
||||||
|
#define T304 30000
|
||||||
|
#define T305 30000
|
||||||
|
#define T308 4000
|
||||||
|
/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
|
||||||
|
/* This makes some tests easier and quicker */
|
||||||
|
/* default value is 90 seconds */
|
||||||
|
#define T309 90000
|
||||||
|
/* T310 can be between 30-120 Seconds. We use 120 Seconds so the user can hear
|
||||||
|
the inband messages */
|
||||||
|
#define T310 120000
|
||||||
|
#define T312 6000
|
||||||
|
#define T313 4000
|
||||||
|
#define T318 4000
|
||||||
|
#define T319 4000
|
||||||
|
#define N303 1
|
||||||
|
#define T_CTRL 180000
|
||||||
|
|
||||||
|
#define THOLD 4000
|
||||||
|
#define TRETRIEVE 4000
|
||||||
|
|
||||||
|
/* private TIMER events */
|
||||||
|
#define CC_T301 0x030101
|
||||||
|
#define CC_T302 0x030201
|
||||||
|
#define CC_T303 0x030301
|
||||||
|
#define CC_T304 0x030401
|
||||||
|
#define CC_T305 0x030501
|
||||||
|
#define CC_T308_1 0x030801
|
||||||
|
#define CC_T308_2 0x030802
|
||||||
|
#define CC_T309 0x030901
|
||||||
|
#define CC_T310 0x031001
|
||||||
|
#define CC_T312 0x031201
|
||||||
|
#define CC_T313 0x031301
|
||||||
|
#define CC_T318 0x031801
|
||||||
|
#define CC_T319 0x031901
|
||||||
|
#define CC_TCTRL 0x031f01
|
||||||
|
#define CC_THOLD 0x03a001
|
||||||
|
#define CC_TRETRIEVE 0x03a101
|
||||||
|
|
||||||
|
#define AUX_IDLE 0
|
||||||
|
#define AUX_HOLD_REQ 1
|
||||||
|
#define AUX_CALL_HELD 2
|
||||||
|
#define AUX_RETRIEVE_REQ 3
|
||||||
|
#define AUX_HOLD_IND 4
|
||||||
|
#define AUX_RETRIEVE_IND 5
|
||||||
|
|
||||||
|
#define VALID_HOLD_STATES_PTMP (SBIT(3) | SBIT(4) | SBIT(10))
|
||||||
|
#define VALID_HOLD_STATES_PTP (SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10))
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Explicit Call Transfer (ECT) Supplementary Services ETS 300 369-1
|
||||||
|
*
|
||||||
|
* ECT Facility ie encode/decode header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASN1_ECT_H
|
||||||
|
#define __ASN1_ECT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int encodeFacEctExecute(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
|
||||||
|
int encodeFacExplicitEctExecute(__u8 * Dest, const struct asn1_parm *pc, const struct FacExplicitEctExecute *ExplicitEctExecute);
|
||||||
|
int ParseExplicitEctExecute(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacExplicitEctExecute *ExplicitEctExecute);
|
||||||
|
|
||||||
|
int encodeFacRequestSubaddress(__u8 * Dest, const struct asn1_parm *pc, const void *val);
|
||||||
|
|
||||||
|
int encodeFacSubaddressTransfer(__u8 * Dest, const struct asn1_parm *pc, const struct FacSubaddressTransfer *SubaddressTransfer);
|
||||||
|
int ParseSubaddressTransfer(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacSubaddressTransfer *SubaddressTransfer);
|
||||||
|
|
||||||
|
int encodeFacEctLinkIdRequest(__u8 * Dest, const struct asn1_parm *pc, const struct FacEctLinkIdRequest_RES *EctLinkIdRequest);
|
||||||
|
int ParseEctLinkIdRequest_RES(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacEctLinkIdRequest_RES *EctLinkIdRequest);
|
||||||
|
|
||||||
|
int encodeFacEctInform(__u8 * Dest, const struct asn1_parm *pc, const struct FacEctInform *EctInform);
|
||||||
|
int ParseEctInform(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctInform *EctInform);
|
||||||
|
|
||||||
|
int encodeFacEctLoopTest(__u8 * Dest, const struct asn1_parm *pc, const struct FacEctLoopTest *EctLoopTest);
|
||||||
|
int ParseEctLoopTest(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctLoopTest *EctLoopTest);
|
||||||
|
int ParseEctLoopTest_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctLoopTest_RES *EctLoopTest);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __ASN1_ECT_H */
|
||||||
|
/* ------------------------------------------------------------------- *//* end asn1_ect.h */
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* $Id: fsm.h,v 2.0 2007/06/29 14:35:31 kkeil Exp $
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Statemachine */
|
||||||
|
|
||||||
|
#include "mtimer.h"
|
||||||
|
|
||||||
|
struct FsmInst;
|
||||||
|
|
||||||
|
typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
|
||||||
|
|
||||||
|
struct Fsm {
|
||||||
|
FSMFNPTR *jumpmatrix;
|
||||||
|
int state_count, event_count;
|
||||||
|
const char **strEvent, **strState;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FsmInst {
|
||||||
|
struct Fsm *fsm;
|
||||||
|
struct timer_base *tb;
|
||||||
|
int state;
|
||||||
|
int debug;
|
||||||
|
void *userdata;
|
||||||
|
int userint;
|
||||||
|
void (*printdebug)(struct FsmInst *, const char *, ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FsmNode {
|
||||||
|
int state, event;
|
||||||
|
void (*routine) (struct FsmInst *, int, void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FsmTimer {
|
||||||
|
struct FsmInst *fi;
|
||||||
|
struct mtimer tl;
|
||||||
|
int event;
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void FsmNew(struct Fsm *, struct FsmNode *, int);
|
||||||
|
extern void FsmFree(struct Fsm *);
|
||||||
|
extern int FsmEvent(struct FsmInst *, int , void *);
|
||||||
|
extern void FsmChangeState(struct FsmInst *, int);
|
||||||
|
extern void FsmInitTimer(struct FsmInst *, struct FsmTimer *);
|
||||||
|
extern int FsmAddTimer(struct FsmTimer *, int, int, void *, int);
|
||||||
|
extern void FsmRestartTimer(struct FsmTimer *, int, int, void *, int);
|
||||||
|
extern void FsmDelTimer(struct FsmTimer *, int);
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* helper.h
|
||||||
|
*
|
||||||
|
* some helper functions
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HELPER_H
|
||||||
|
#define _HELPER_H
|
||||||
|
|
||||||
|
#undef offsetof
|
||||||
|
#ifdef __compiler_offsetof
|
||||||
|
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
|
||||||
|
#else
|
||||||
|
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* container_of - cast a member of a structure out to the containing structure
|
||||||
|
* @ptr: the pointer to the member.
|
||||||
|
* @type: the type of the container struct this is embedded in.
|
||||||
|
* @member: the name of the member within the struct.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define container_of(ptr, type, member) ({ \
|
||||||
|
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||||
|
|
||||||
|
|
||||||
|
/* Simple replacement for the NON-ATOMIC routines which asm/bitops.h
|
||||||
|
was providing. */
|
||||||
|
|
||||||
|
static inline int test_bit(int bit, unsigned long *word)
|
||||||
|
{
|
||||||
|
return !!((*word) & (1<<bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int test_and_clear_bit(int bit, unsigned long *word)
|
||||||
|
{
|
||||||
|
int ret = !!((*word) & (1<<bit));
|
||||||
|
|
||||||
|
*word &= ~(1<<bit);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int test_and_set_bit(int bit, unsigned long *word)
|
||||||
|
{
|
||||||
|
int ret = !!((*word) & (1<<bit));
|
||||||
|
|
||||||
|
*word |= 1<<bit;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_bit(int bit, unsigned long *word)
|
||||||
|
{
|
||||||
|
*word &= ~(1<<bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_bit(int bit, unsigned long *word)
|
||||||
|
{
|
||||||
|
*word |= 1<<bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* layer3.h
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LAYER3_H
|
||||||
|
#define LAYER3_H
|
||||||
|
|
||||||
|
#include <mISDN/mbuffer.h>
|
||||||
|
#include "helper.h"
|
||||||
|
#include "mlist.h"
|
||||||
|
#include "mtimer.h"
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
typedef struct _l3_process l3_process_t;
|
||||||
|
|
||||||
|
struct _layer3;
|
||||||
|
|
||||||
|
struct l3protocol {
|
||||||
|
const char *name;
|
||||||
|
unsigned int protocol;
|
||||||
|
void (*init)(struct _layer3 *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct L3Timer {
|
||||||
|
struct mtimer tl;
|
||||||
|
struct _layer3 *l3;
|
||||||
|
unsigned int pid;
|
||||||
|
unsigned int nr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l2l3if;
|
||||||
|
|
||||||
|
struct _l3_process {
|
||||||
|
struct list_head list;
|
||||||
|
struct _layer3 *L3;
|
||||||
|
struct l2l3if *l2if;
|
||||||
|
l3_process_t *master;
|
||||||
|
struct list_head child;
|
||||||
|
unsigned long flags;
|
||||||
|
int pid;
|
||||||
|
int selpid;
|
||||||
|
int state;
|
||||||
|
struct L3Timer timer1;
|
||||||
|
struct L3Timer timer2;
|
||||||
|
int n303;
|
||||||
|
struct l3_msg *t303msg;
|
||||||
|
unsigned char cid[4];
|
||||||
|
int cause;
|
||||||
|
int rm_cause;
|
||||||
|
int aux_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FLG_L3P_TIMER312 1
|
||||||
|
#define FLG_L3P_TIMER303_1 2
|
||||||
|
#define FLG_L3P_TIMER308_1 3
|
||||||
|
#define FLG_L3P_TIMER309 4
|
||||||
|
#define FLG_L3P_GOTRELCOMP 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* maximum orginated callrefs
|
||||||
|
* have to be a multiple of 8
|
||||||
|
*/
|
||||||
|
#define MAX_PID_COUNT 128
|
||||||
|
|
||||||
|
struct l2l3if {
|
||||||
|
struct list_head list;
|
||||||
|
struct _layer3 *l3;
|
||||||
|
struct sockaddr_mISDN l2addr;
|
||||||
|
struct FsmInst l3m;
|
||||||
|
struct FsmTimer l3m_timer;
|
||||||
|
struct mqueue squeue;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _layer3 {
|
||||||
|
struct mlayer3 ml3;
|
||||||
|
pthread_t worker;
|
||||||
|
int l2sock;
|
||||||
|
void *l2inst;
|
||||||
|
int maxfd;
|
||||||
|
struct l2l3if l2master;
|
||||||
|
struct timer_base tbase;
|
||||||
|
int next_cr;
|
||||||
|
struct list_head plist;
|
||||||
|
l3_process_t global;
|
||||||
|
l3_process_t dummy;
|
||||||
|
int (*p_mgr)(l3_process_t *, u_int, struct l3_msg *);
|
||||||
|
int (*from_l2)(struct _layer3 *, struct mbuffer *);
|
||||||
|
int (*to_l3)(struct _layer3 *, struct l3_msg *);
|
||||||
|
int debug;
|
||||||
|
struct mqueue app_queue;
|
||||||
|
struct mqueue mgr_queue;
|
||||||
|
pthread_mutex_t run;
|
||||||
|
} layer3_t;
|
||||||
|
|
||||||
|
struct stateentry {
|
||||||
|
unsigned int state;
|
||||||
|
unsigned int primitive;
|
||||||
|
void (*rout) (l3_process_t *, unsigned int, struct l3_msg *);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern l3_process_t *get_l3process4pid(layer3_t *, unsigned int);
|
||||||
|
extern l3_process_t *get_l3process4cref(layer3_t *, unsigned int);
|
||||||
|
extern l3_process_t *create_new_process(layer3_t *, unsigned int, unsigned int, l3_process_t *);
|
||||||
|
extern void release_l3_process(struct _l3_process *);
|
||||||
|
extern void SendMsg(struct _l3_process *, struct l3_msg *, int);
|
||||||
|
extern void mISDN_l3up(l3_process_t *, unsigned int, struct l3_msg *);
|
||||||
|
extern void mIl3_debug(layer3_t *, const char *, ...);
|
||||||
|
extern void mIpc_debug(u_int, struct _l3_process *, const char *, ...);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
newl3state(l3_process_t *pc, int state)
|
||||||
|
{
|
||||||
|
mIpc_debug(L3_DEB_STATE, pc, "state %d --> %d", pc->state, state);
|
||||||
|
pc->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct l3_msg *
|
||||||
|
MsgStart(l3_process_t *pc, unsigned char mt)
|
||||||
|
{
|
||||||
|
struct l3_msg *l3m;
|
||||||
|
struct mbuffer *mb;
|
||||||
|
|
||||||
|
l3m = alloc_l3_msg();
|
||||||
|
if (!l3m)
|
||||||
|
return NULL;
|
||||||
|
mb = container_of(l3m, struct mbuffer, l3);
|
||||||
|
l3m->type = mt;
|
||||||
|
mb->l3h.type = mt;
|
||||||
|
l3m->pid = pc->pid;
|
||||||
|
return(l3m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* L3 timer functions */
|
||||||
|
extern void StopAllL3Timer(struct _l3_process *);
|
||||||
|
extern void L3AddTimer(struct L3Timer *, int, unsigned int);
|
||||||
|
extern void L3DelTimer(struct L3Timer *);
|
||||||
|
extern void l3_manager(struct l2l3if *, unsigned int);
|
||||||
|
|
||||||
|
extern int assembleQ931(struct _l3_process *, struct l3_msg *);
|
||||||
|
|
||||||
|
#define SBIT(state) (1 << state)
|
||||||
|
#define ALL_STATES 0xffffffff
|
||||||
|
|
||||||
|
/*
|
||||||
|
* internal used property flags
|
||||||
|
* 0...15 reserved for set properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FLG_USER 16
|
||||||
|
#define FLG_NETWORK 17
|
||||||
|
#define FLG_BASICRATE 18
|
||||||
|
#define FLG_L2BLOCK 19
|
||||||
|
#define FLG_RUN_WAIT 30
|
||||||
|
#define FLG_ABORT 31
|
||||||
|
|
||||||
|
extern void init_l3(layer3_t *);
|
||||||
|
extern void release_l3(layer3_t *);
|
||||||
|
extern int l3_start(struct _layer3 *);
|
||||||
|
extern void l3_stop(struct _layer3 *);
|
||||||
|
extern int layer3_work(struct _layer3 *l3);
|
||||||
|
extern void mISDNl3New(void);
|
||||||
|
extern void mISDNl3Free(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*af_isdn.h
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2010 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* simple implementation to allow different values for
|
||||||
|
* AF_ISDN/PF_ISDN
|
||||||
|
*
|
||||||
|
* Important notes:
|
||||||
|
*
|
||||||
|
* This file is C code, not only declarations, so a program should only
|
||||||
|
* include it in one code file, best in the file containing main() as well.
|
||||||
|
* Programs using libmisdn do not need that file, since libmisdn already have
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int __af_isdn = MISDN_AF_ISDN;
|
||||||
|
|
||||||
|
int set_af_isdn(int af)
|
||||||
|
{
|
||||||
|
if (af < 0)
|
||||||
|
return -1;
|
||||||
|
if (af >= AF_MAX)
|
||||||
|
return -1;
|
||||||
|
__af_isdn = af;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* $Id: l3dss1.h,v 2.0 2007/06/29 14:08:15 kkeil Exp $
|
||||||
|
*
|
||||||
|
* DSS1 (Euro) D-channel protocol defines
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _L3DSS1_H
|
||||||
|
#define _L3DSS1_H
|
||||||
|
|
||||||
|
#define T301 180000
|
||||||
|
#define T302 15000
|
||||||
|
#define T303 4000
|
||||||
|
#define T304 30000
|
||||||
|
#define T305 30000
|
||||||
|
#define T308 4000
|
||||||
|
/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
|
||||||
|
/* This makes some tests easier and quicker */
|
||||||
|
#define T309 40000
|
||||||
|
#define T310 30000
|
||||||
|
#define T312 6000
|
||||||
|
#define T313 4000
|
||||||
|
#define T318 4000
|
||||||
|
#define T319 4000
|
||||||
|
#define N303 1
|
||||||
|
#define T_CTRL 180000
|
||||||
|
|
||||||
|
/* private TIMER events */
|
||||||
|
#define CC_TIMER 0x000001
|
||||||
|
#define CC_T301 0x030101
|
||||||
|
#define CC_T302 0x030201
|
||||||
|
#define CC_T303 0x030301
|
||||||
|
#define CC_T304 0x030401
|
||||||
|
#define CC_T305 0x030501
|
||||||
|
#define CC_T308 0x030801
|
||||||
|
#define CC_T309 0x030901
|
||||||
|
#define CC_T310 0x031001
|
||||||
|
#define CC_T312 0x031201
|
||||||
|
#define CC_T313 0x031301
|
||||||
|
#define CC_T318 0x031801
|
||||||
|
#define CC_T319 0x031901
|
||||||
|
#define CC_TCTRL 0x031f01
|
||||||
|
#define HOLDAUX_IDLE 0
|
||||||
|
#define HOLDAUX_HOLD_REQ 1
|
||||||
|
#define HOLDAUX_HOLD 2
|
||||||
|
#define HOLDAUX_RETR_REQ 3
|
||||||
|
#define HOLDAUX_HOLD_IND 4
|
||||||
|
#define HOLDAUX_RETR_IND 5
|
||||||
|
|
||||||
|
|
||||||
|
/* l3dss1 specific data in l3 process */
|
||||||
|
typedef struct
|
||||||
|
{ unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */
|
||||||
|
ulong ll_id; /* remebered ll id */
|
||||||
|
u_char remote_operation; /* handled remote operation, 0 = not active */
|
||||||
|
int proc; /* rememered procedure */
|
||||||
|
ulong remote_result; /* result of remote operation for statcallb */
|
||||||
|
char uus1_data[35]; /* data send during alerting or disconnect */
|
||||||
|
} dss1_proc_priv;
|
||||||
|
|
||||||
|
/* l3dss1 specific data in protocol stack */
|
||||||
|
typedef struct
|
||||||
|
{ unsigned char last_invoke_id; /* last used value for invoking */
|
||||||
|
unsigned char invoke_used[32]; /* 256 bits for 256 values */
|
||||||
|
} dss1_stk_priv;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
// to be compatible...
|
||||||
|
|
||||||
|
#define MISDN_AF_ISDN 34
|
||||||
|
|
|
@ -0,0 +1,420 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef mISDNIF_H
|
||||||
|
#define mISDNIF_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/socket.h>
|
||||||
|
#include <mISDN/mISDNcompat.h>
|
||||||
|
|
||||||
|
#define MISDN_GIT_RELEASE 0x4000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ABI Version 32 bit
|
||||||
|
*
|
||||||
|
* <8 bit> Major version
|
||||||
|
* - changed if any interface become backwards incompatible
|
||||||
|
*
|
||||||
|
* <8 bit> Minor version
|
||||||
|
* - changed if any interface is extended but backwards compatible
|
||||||
|
*
|
||||||
|
* <14 bit> Release number
|
||||||
|
* - should be incremented on every checkin
|
||||||
|
*
|
||||||
|
* <bit 15> set in kernel version IOCTL is used to mark it as git.misdn.eu version
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define MISDN_MAJOR_VERSION 1
|
||||||
|
#define MISDN_MINOR_VERSION 1
|
||||||
|
#define MISDN_RELEASE 31
|
||||||
|
|
||||||
|
/* primitives for information exchange
|
||||||
|
* generell format
|
||||||
|
* <16 bit 0 >
|
||||||
|
* <8 bit command>
|
||||||
|
* BIT 8 = 1 LAYER private
|
||||||
|
* BIT 7 = 1 answer
|
||||||
|
* BIT 6 = 1 DATA
|
||||||
|
* <8 bit target layer mask>
|
||||||
|
*
|
||||||
|
* Layer = 00 is reserved for general commands
|
||||||
|
Layer = 01 L2 -> HW
|
||||||
|
Layer = 02 HW -> L2
|
||||||
|
Layer = 04 L3 -> L2
|
||||||
|
Layer = 08 L2 -> L3
|
||||||
|
* Layer = FF is reserved for broadcast commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MISDN_CMDMASK 0xff00
|
||||||
|
#define MISDN_LAYERMASK 0x00ff
|
||||||
|
|
||||||
|
/* generell commands */
|
||||||
|
#define OPEN_CHANNEL 0x0100
|
||||||
|
#define CLOSE_CHANNEL 0x0200
|
||||||
|
#define CONTROL_CHANNEL 0x0300
|
||||||
|
#define CHECK_DATA 0x0400
|
||||||
|
|
||||||
|
/* layer 2 -> layer 1 */
|
||||||
|
#define PH_ACTIVATE_REQ 0x0101
|
||||||
|
#define PH_DEACTIVATE_REQ 0x0201
|
||||||
|
#define PH_DATA_REQ 0x2001
|
||||||
|
#define MPH_ACTIVATE_REQ 0x0501
|
||||||
|
#define MPH_DEACTIVATE_REQ 0x0601
|
||||||
|
#define MPH_INFORMATION_REQ 0x0701
|
||||||
|
#define PH_CONTROL_REQ 0x0801
|
||||||
|
|
||||||
|
/* layer 1 -> layer 2 */
|
||||||
|
#define PH_ACTIVATE_IND 0x0102
|
||||||
|
#define PH_ACTIVATE_CNF 0x4102
|
||||||
|
#define PH_DEACTIVATE_IND 0x0202
|
||||||
|
#define PH_DEACTIVATE_CNF 0x4202
|
||||||
|
#define PH_DATA_IND 0x2002
|
||||||
|
#define PH_DATA_E_IND 0x3002
|
||||||
|
#define MPH_ACTIVATE_IND 0x0502
|
||||||
|
#define MPH_DEACTIVATE_IND 0x0602
|
||||||
|
#define MPH_INFORMATION_IND 0x0702
|
||||||
|
#define PH_DATA_CNF 0x6002
|
||||||
|
#define PH_CONTROL_IND 0x0802
|
||||||
|
#define PH_CONTROL_CNF 0x4802
|
||||||
|
|
||||||
|
/* layer 3 -> layer 2 */
|
||||||
|
#define DL_ESTABLISH_REQ 0x1004
|
||||||
|
#define DL_RELEASE_REQ 0x1104
|
||||||
|
#define DL_DATA_REQ 0x3004
|
||||||
|
#define DL_UNITDATA_REQ 0x3104
|
||||||
|
#define DL_INFORMATION_REQ 0x0004
|
||||||
|
|
||||||
|
/* layer 2 -> layer 3 */
|
||||||
|
#define DL_ESTABLISH_IND 0x1008
|
||||||
|
#define DL_ESTABLISH_CNF 0x5008
|
||||||
|
#define DL_RELEASE_IND 0x1108
|
||||||
|
#define DL_RELEASE_CNF 0x5108
|
||||||
|
#define DL_DATA_IND 0x3008
|
||||||
|
#define DL_UNITDATA_IND 0x3108
|
||||||
|
#define DL_INFORMATION_IND 0x0008
|
||||||
|
|
||||||
|
/* intern layer 2 management */
|
||||||
|
#define MDL_ASSIGN_REQ 0x1804
|
||||||
|
#define MDL_ASSIGN_IND 0x1904
|
||||||
|
#define MDL_REMOVE_REQ 0x1A04
|
||||||
|
#define MDL_REMOVE_IND 0x1B04
|
||||||
|
#define MDL_STATUS_UP_IND 0x1C04
|
||||||
|
#define MDL_STATUS_DOWN_IND 0x1D04
|
||||||
|
#define MDL_STATUS_UI_IND 0x1E04
|
||||||
|
#define MDL_ERROR_IND 0x1F04
|
||||||
|
#define MDL_ERROR_RSP 0x5F04
|
||||||
|
|
||||||
|
/* intern layer 2 */
|
||||||
|
#define DL_TIMER200_IND 0x7004
|
||||||
|
#define DL_TIMER203_IND 0x7304
|
||||||
|
#define DL_INTERN_MSG 0x7804
|
||||||
|
|
||||||
|
/* DL_INFORMATION_IND types */
|
||||||
|
#define DL_INFO_L2_CONNECT 0x0001
|
||||||
|
#define DL_INFO_L2_REMOVED 0x0002
|
||||||
|
|
||||||
|
/* PH_CONTROL types */
|
||||||
|
/* TOUCH TONE IS 0x20XX XX "0"..."9", "A","B","C","D","*","#" */
|
||||||
|
#define DTMF_TONE_VAL 0x2000
|
||||||
|
#define DTMF_TONE_MASK 0x007F
|
||||||
|
#define DTMF_TONE_START 0x2100
|
||||||
|
#define DTMF_TONE_STOP 0x2200
|
||||||
|
#define DTMF_HFC_COEF 0x4000
|
||||||
|
#define DSP_CONF_JOIN 0x2403
|
||||||
|
#define DSP_CONF_SPLIT 0x2404
|
||||||
|
#define DSP_RECEIVE_OFF 0x2405
|
||||||
|
#define DSP_RECEIVE_ON 0x2406
|
||||||
|
#define DSP_ECHO_ON 0x2407
|
||||||
|
#define DSP_ECHO_OFF 0x2408
|
||||||
|
#define DSP_MIX_ON 0x2409
|
||||||
|
#define DSP_MIX_OFF 0x240a
|
||||||
|
#define DSP_DELAY 0x240b
|
||||||
|
#define DSP_JITTER 0x240c
|
||||||
|
#define DSP_TXDATA_ON 0x240d
|
||||||
|
#define DSP_TXDATA_OFF 0x240e
|
||||||
|
#define DSP_TX_DEJITTER 0x240f
|
||||||
|
#define DSP_TX_DEJ_OFF 0x2410
|
||||||
|
#define DSP_TONE_PATT_ON 0x2411
|
||||||
|
#define DSP_TONE_PATT_OFF 0x2412
|
||||||
|
#define DSP_VOL_CHANGE_TX 0x2413
|
||||||
|
#define DSP_VOL_CHANGE_RX 0x2414
|
||||||
|
#define DSP_BF_ENABLE_KEY 0x2415
|
||||||
|
#define DSP_BF_DISABLE 0x2416
|
||||||
|
#define DSP_BF_ACCEPT 0x2416
|
||||||
|
#define DSP_BF_REJECT 0x2417
|
||||||
|
#define DSP_PIPELINE_CFG 0x2418
|
||||||
|
#define HFC_VOL_CHANGE_TX 0x2601
|
||||||
|
#define HFC_VOL_CHANGE_RX 0x2602
|
||||||
|
#define HFC_SPL_LOOP_ON 0x2603
|
||||||
|
#define HFC_SPL_LOOP_OFF 0x2604
|
||||||
|
/* for T30 FAX and analog modem */
|
||||||
|
#define HW_MOD_FRM 0x4000
|
||||||
|
#define HW_MOD_FRH 0x4001
|
||||||
|
#define HW_MOD_FTM 0x4002
|
||||||
|
#define HW_MOD_FTH 0x4003
|
||||||
|
#define HW_MOD_FTS 0x4004
|
||||||
|
#define HW_MOD_CONNECT 0x4010
|
||||||
|
#define HW_MOD_OK 0x4011
|
||||||
|
#define HW_MOD_NOCARR 0x4012
|
||||||
|
#define HW_MOD_FCERROR 0x4013
|
||||||
|
#define HW_MOD_READY 0x4014
|
||||||
|
#define HW_MOD_LASTDATA 0x4015
|
||||||
|
|
||||||
|
/* DSP_TONE_PATT_ON parameter */
|
||||||
|
#define TONE_OFF 0x0000
|
||||||
|
#define TONE_GERMAN_DIALTONE 0x0001
|
||||||
|
#define TONE_GERMAN_OLDDIALTONE 0x0002
|
||||||
|
#define TONE_AMERICAN_DIALTONE 0x0003
|
||||||
|
#define TONE_GERMAN_DIALPBX 0x0004
|
||||||
|
#define TONE_GERMAN_OLDDIALPBX 0x0005
|
||||||
|
#define TONE_AMERICAN_DIALPBX 0x0006
|
||||||
|
#define TONE_GERMAN_RINGING 0x0007
|
||||||
|
#define TONE_GERMAN_OLDRINGING 0x0008
|
||||||
|
#define TONE_AMERICAN_RINGPBX 0x000b
|
||||||
|
#define TONE_GERMAN_RINGPBX 0x000c
|
||||||
|
#define TONE_GERMAN_OLDRINGPBX 0x000d
|
||||||
|
#define TONE_AMERICAN_RINGING 0x000e
|
||||||
|
#define TONE_GERMAN_BUSY 0x000f
|
||||||
|
#define TONE_GERMAN_OLDBUSY 0x0010
|
||||||
|
#define TONE_AMERICAN_BUSY 0x0011
|
||||||
|
#define TONE_GERMAN_HANGUP 0x0012
|
||||||
|
#define TONE_GERMAN_OLDHANGUP 0x0013
|
||||||
|
#define TONE_AMERICAN_HANGUP 0x0014
|
||||||
|
#define TONE_SPECIAL_INFO 0x0015
|
||||||
|
#define TONE_GERMAN_GASSENBESETZT 0x0016
|
||||||
|
#define TONE_GERMAN_AUFSCHALTTON 0x0016
|
||||||
|
|
||||||
|
/* MPH_INFORMATION_IND */
|
||||||
|
#define L1_SIGNAL_LOS_OFF 0x0010
|
||||||
|
#define L1_SIGNAL_LOS_ON 0x0011
|
||||||
|
#define L1_SIGNAL_AIS_OFF 0x0012
|
||||||
|
#define L1_SIGNAL_AIS_ON 0x0013
|
||||||
|
#define L1_SIGNAL_RDI_OFF 0x0014
|
||||||
|
#define L1_SIGNAL_RDI_ON 0x0015
|
||||||
|
#define L1_SIGNAL_SLIP_RX 0x0020
|
||||||
|
#define L1_SIGNAL_SLIP_TX 0x0021
|
||||||
|
|
||||||
|
/*
|
||||||
|
* protocol ids
|
||||||
|
* D channel 1-31
|
||||||
|
* B channel 33 - 63
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ISDN_P_NONE 0
|
||||||
|
#define ISDN_P_BASE 0
|
||||||
|
#define ISDN_P_TE_S0 0x01
|
||||||
|
#define ISDN_P_NT_S0 0x02
|
||||||
|
#define ISDN_P_TE_E1 0x03
|
||||||
|
#define ISDN_P_NT_E1 0x04
|
||||||
|
#define ISDN_P_TE_UP0 0x05
|
||||||
|
#define ISDN_P_NT_UP0 0x06
|
||||||
|
|
||||||
|
#define IS_ISDN_P_TE(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_TE_E1) || \
|
||||||
|
(p == ISDN_P_TE_UP0) || (p == ISDN_P_LAPD_TE))
|
||||||
|
#define IS_ISDN_P_NT(p) ((p == ISDN_P_NT_S0) || (p == ISDN_P_NT_E1) || \
|
||||||
|
(p == ISDN_P_NT_UP0) || (p == ISDN_P_LAPD_NT))
|
||||||
|
#define IS_ISDN_P_S0(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_NT_S0))
|
||||||
|
#define IS_ISDN_P_E1(p) ((p == ISDN_P_TE_E1) || (p == ISDN_P_NT_E1))
|
||||||
|
#define IS_ISDN_P_UP0(p) ((p == ISDN_P_TE_UP0) || (p == ISDN_P_NT_UP0))
|
||||||
|
|
||||||
|
|
||||||
|
#define ISDN_P_LAPD_TE 0x10
|
||||||
|
#define ISDN_P_LAPD_NT 0x11
|
||||||
|
|
||||||
|
#define ISDN_P_B_MASK 0x1f
|
||||||
|
#define ISDN_P_B_START 0x20
|
||||||
|
|
||||||
|
#define ISDN_P_B_RAW 0x21
|
||||||
|
#define ISDN_P_B_HDLC 0x22
|
||||||
|
#define ISDN_P_B_X75SLP 0x23
|
||||||
|
#define ISDN_P_B_L2DTMF 0x24
|
||||||
|
#define ISDN_P_B_L2DSP 0x25
|
||||||
|
#define ISDN_P_B_L2DSPHDLC 0x26
|
||||||
|
#define ISDN_P_B_T30_FAX 0x27
|
||||||
|
#define ISDN_P_B_MODEM_ASYNC 0x28
|
||||||
|
|
||||||
|
#define OPTION_L2_PMX 1
|
||||||
|
#define OPTION_L2_PTP 2
|
||||||
|
#define OPTION_L2_FIXEDTEI 3
|
||||||
|
#define OPTION_L2_CLEANUP 4
|
||||||
|
#define OPTION_L1_HOLD 5
|
||||||
|
|
||||||
|
/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
|
||||||
|
#define MISDN_MAX_IDLEN 20
|
||||||
|
|
||||||
|
struct mISDNhead {
|
||||||
|
unsigned int prim;
|
||||||
|
unsigned int id;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define MISDN_HEADER_LEN sizeof(struct mISDNhead)
|
||||||
|
#define MAX_DATA_SIZE 2048
|
||||||
|
#define MAX_DATA_MEM (MAX_DATA_SIZE + MISDN_HEADER_LEN)
|
||||||
|
#define MAX_DFRAME_LEN 260
|
||||||
|
|
||||||
|
#define MISDN_ID_ADDR_MASK 0xFFFF
|
||||||
|
#define MISDN_ID_TEI_MASK 0xFF00
|
||||||
|
#define MISDN_ID_SAPI_MASK 0x00FF
|
||||||
|
#define MISDN_ID_TEI_ANY 0x7F00
|
||||||
|
|
||||||
|
#define MISDN_ID_ANY 0xFFFF
|
||||||
|
#define MISDN_ID_NONE 0xFFFE
|
||||||
|
|
||||||
|
#define GROUP_TEI 127
|
||||||
|
#define TEI_SAPI 63
|
||||||
|
#define CTRL_SAPI 0
|
||||||
|
|
||||||
|
#define MISDN_MAX_CHANNEL 127
|
||||||
|
#define MISDN_CHMAP_SIZE ((MISDN_MAX_CHANNEL + 1) >> 3)
|
||||||
|
|
||||||
|
#define SOL_MISDN 0
|
||||||
|
|
||||||
|
struct sockaddr_mISDN {
|
||||||
|
sa_family_t family;
|
||||||
|
unsigned char dev;
|
||||||
|
unsigned char channel;
|
||||||
|
unsigned char sapi;
|
||||||
|
unsigned char tei;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mISDNversion {
|
||||||
|
unsigned char major;
|
||||||
|
unsigned char minor;
|
||||||
|
unsigned short release;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_DEVICE_ID 63
|
||||||
|
|
||||||
|
struct mISDN_devinfo {
|
||||||
|
u_int id;
|
||||||
|
u_int Dprotocols;
|
||||||
|
u_int Bprotocols;
|
||||||
|
u_int protocol;
|
||||||
|
u_char channelmap[MISDN_CHMAP_SIZE];
|
||||||
|
u_int nrbchan;
|
||||||
|
char name[MISDN_MAX_IDLEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mISDN_devrename {
|
||||||
|
u_int id;
|
||||||
|
char name[MISDN_MAX_IDLEN]; /* new name */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* MPH_INFORMATION_REQ payload */
|
||||||
|
struct ph_info_ch {
|
||||||
|
__u32 protocol;
|
||||||
|
__u64 Flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ph_info_dch {
|
||||||
|
struct ph_info_ch ch;
|
||||||
|
__u16 state;
|
||||||
|
__u16 num_bch;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ph_info {
|
||||||
|
struct ph_info_dch dch;
|
||||||
|
struct ph_info_ch bch[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* timer device ioctl */
|
||||||
|
#define IMADDTIMER _IOR('I', 64, int)
|
||||||
|
#define IMDELTIMER _IOR('I', 65, int)
|
||||||
|
|
||||||
|
/* socket ioctls */
|
||||||
|
#define IMGETVERSION _IOR('I', 66, int)
|
||||||
|
#define IMGETCOUNT _IOR('I', 67, int)
|
||||||
|
#define IMGETDEVINFO _IOR('I', 68, int)
|
||||||
|
#define IMCTRLREQ _IOR('I', 69, int)
|
||||||
|
#define IMCLEAR_L2 _IOR('I', 70, int)
|
||||||
|
#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename)
|
||||||
|
#define IMHOLD_L1 _IOR('I', 72, int)
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
test_channelmap(u_int nr, u_char *map)
|
||||||
|
{
|
||||||
|
if (nr <= MISDN_MAX_CHANNEL)
|
||||||
|
return map[nr >> 3] & (1 << (nr & 7));
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_channelmap(u_int nr, u_char *map)
|
||||||
|
{
|
||||||
|
map[nr >> 3] |= (1 << (nr & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
clear_channelmap(u_int nr, u_char *map)
|
||||||
|
{
|
||||||
|
map[nr >> 3] &= ~(1 << (nr & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CONTROL_CHANNEL parameters */
|
||||||
|
#define MISDN_CTRL_GETOP 0x0000
|
||||||
|
#define MISDN_CTRL_LOOP 0x0001
|
||||||
|
#define MISDN_CTRL_CONNECT 0x0002
|
||||||
|
#define MISDN_CTRL_DISCONNECT 0x0004
|
||||||
|
#define MISDN_CTRL_RX_BUFFER 0x0008
|
||||||
|
#define MISDN_CTRL_PCMCONNECT 0x0010
|
||||||
|
#define MISDN_CTRL_PCMDISCONNECT 0x0020
|
||||||
|
#define MISDN_CTRL_SETPEER 0x0040
|
||||||
|
#define MISDN_CTRL_UNSETPEER 0x0080
|
||||||
|
#define MISDN_CTRL_RX_OFF 0x0100
|
||||||
|
#define MISDN_CTRL_FILL_EMPTY 0x0200
|
||||||
|
#define MISDN_CTRL_GETPEER 0x0400
|
||||||
|
#define MISDN_CTRL_L1_TIMER3 0x0800
|
||||||
|
#define MISDN_CTRL_HW_FEATURES_OP 0x2000
|
||||||
|
#define MISDN_CTRL_HW_FEATURES 0x2001
|
||||||
|
#define MISDN_CTRL_HFC_OP 0x4000
|
||||||
|
#define MISDN_CTRL_HFC_PCM_CONN 0x4001
|
||||||
|
#define MISDN_CTRL_HFC_PCM_DISC 0x4002
|
||||||
|
#define MISDN_CTRL_HFC_CONF_JOIN 0x4003
|
||||||
|
#define MISDN_CTRL_HFC_CONF_SPLIT 0x4004
|
||||||
|
#define MISDN_CTRL_HFC_RECEIVE_OFF 0x4005
|
||||||
|
#define MISDN_CTRL_HFC_RECEIVE_ON 0x4006
|
||||||
|
#define MISDN_CTRL_HFC_ECHOCAN_ON 0x4007
|
||||||
|
#define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008
|
||||||
|
#define MISDN_CTRL_HFC_WD_INIT 0x4009
|
||||||
|
#define MISDN_CTRL_HFC_WD_RESET 0x400A
|
||||||
|
|
||||||
|
/* special RX buffer value for MISDN_CTRL_RX_BUFFER request.p1 is the minimum
|
||||||
|
* buffer size request.p2 the maximum. Using MISDN_CTRL_RX_SIZE_IGNORE will
|
||||||
|
* not change the value, but still read back the actual stetting.
|
||||||
|
*/
|
||||||
|
#define MISDN_CTRL_RX_SIZE_IGNORE -1
|
||||||
|
|
||||||
|
/* socket options */
|
||||||
|
#define MISDN_TIME_STAMP 0x0001
|
||||||
|
|
||||||
|
struct mISDN_ctrl_req {
|
||||||
|
int op;
|
||||||
|
int channel;
|
||||||
|
int p1;
|
||||||
|
int p2;
|
||||||
|
int unused; /* temporary support for older git.misdn.eu drivers */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* muxer options */
|
||||||
|
#define MISDN_OPT_ALL 1
|
||||||
|
#define MISDN_OPT_TEIMGR 2
|
||||||
|
|
||||||
|
#endif /* mISDNIF_H */
|
|
@ -0,0 +1,259 @@
|
||||||
|
/* mbuffer.h
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MBUFFER_H
|
||||||
|
#define _MBUFFER_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <mISDN/mISDNif.h>
|
||||||
|
#include <mISDN/mlayer3.h>
|
||||||
|
|
||||||
|
#ifndef eprint
|
||||||
|
#define eprint(fmt, ...) mi_printf(__FILE__, __LINE__, __PRETTY_FUNCTION__, 1, fmt, ##__VA_ARGS__)
|
||||||
|
extern int mi_printf(const char *file, int line, const char *func, int lev, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mqueue {
|
||||||
|
struct mbuffer *prev;
|
||||||
|
struct mbuffer *next;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
struct lhead {
|
||||||
|
struct lhead *prev;
|
||||||
|
struct lhead *next;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mbuffer {
|
||||||
|
struct mbuffer *prev;
|
||||||
|
struct mbuffer *next;
|
||||||
|
struct mqueue *list;
|
||||||
|
int refcnt;
|
||||||
|
struct mISDNhead *h;
|
||||||
|
struct sockaddr_mISDN addr;
|
||||||
|
unsigned char *head;
|
||||||
|
unsigned char *data;
|
||||||
|
unsigned char *tail;
|
||||||
|
unsigned char *end;
|
||||||
|
unsigned char *chead;
|
||||||
|
unsigned char *ctail;
|
||||||
|
unsigned char *cend;
|
||||||
|
int len;
|
||||||
|
struct l3_head l3h;
|
||||||
|
struct l3_msg l3;
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
struct lhead Alist;
|
||||||
|
char d_fn[80];
|
||||||
|
int d_ln;
|
||||||
|
#endif
|
||||||
|
} __attribute__((__may_alias__));
|
||||||
|
|
||||||
|
#define MBUFFER_DATA_SIZE 280
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init mbuffer caching
|
||||||
|
* @parameter count of cached mbuffers
|
||||||
|
*/
|
||||||
|
extern void init_mbuffer(int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free the cache
|
||||||
|
*/
|
||||||
|
extern void cleanup_mbuffer(void);
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
/*
|
||||||
|
* alloc a new mbuffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern struct mbuffer *__alloc_mbuffer(const char *file, int lineno, const char *func);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free the message
|
||||||
|
*/
|
||||||
|
extern void __free_mbuffer(struct mbuffer *, const char *file, int lineno, const char *func);
|
||||||
|
|
||||||
|
#define alloc_mbuffer() __alloc_mbuffer(__FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
#define free_mbuffer(p) __free_mbuffer(p, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* alloc a new mbuffer
|
||||||
|
*/
|
||||||
|
extern struct mbuffer *alloc_mbuffer(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free the message
|
||||||
|
*/
|
||||||
|
extern void free_mbuffer(struct mbuffer *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mqueue_init(struct mqueue *q)
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&q->lock, NULL);
|
||||||
|
q->len = 0;
|
||||||
|
q->prev = (struct mbuffer *)q;
|
||||||
|
q->next = (struct mbuffer *)q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int mqueue_len(struct mqueue *q)
|
||||||
|
{
|
||||||
|
return(q->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mqueue_head(struct mqueue *q, struct mbuffer *newm)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
newm->list = q;
|
||||||
|
q->len++;
|
||||||
|
q->next->prev = newm;
|
||||||
|
newm->next = q->next;
|
||||||
|
newm->prev = (struct mbuffer *)q;
|
||||||
|
q->next = newm;
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void mqueue_tail(struct mqueue *q, struct mbuffer *newm)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
newm->list = q;
|
||||||
|
q->len++;
|
||||||
|
q->prev->next = newm;
|
||||||
|
newm->next = (struct mbuffer *)q;;
|
||||||
|
newm->prev = q->prev;
|
||||||
|
q->prev = newm;
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct mbuffer *mdequeue(struct mqueue *q)
|
||||||
|
{
|
||||||
|
struct mbuffer *next, *prev, *result;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
prev = (struct mbuffer *)q;
|
||||||
|
next = prev->next;
|
||||||
|
result = NULL;
|
||||||
|
if (next != prev) {
|
||||||
|
result = next;
|
||||||
|
next = next->next;
|
||||||
|
q->len--;
|
||||||
|
next->prev = prev;
|
||||||
|
prev->next = next;
|
||||||
|
result->list = NULL;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void mqueue_purge(struct mqueue *q)
|
||||||
|
{
|
||||||
|
struct mbuffer *mb;
|
||||||
|
|
||||||
|
while ((mb = mdequeue(q))!=NULL)
|
||||||
|
free_mbuffer(mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ unsigned char *msg_put(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = msg->tail;
|
||||||
|
|
||||||
|
msg->tail += len;
|
||||||
|
msg->len += len;
|
||||||
|
if (msg->tail > msg->end) {
|
||||||
|
eprint("msg_over_panic msg(%p) data(%p) head(%p)\n",
|
||||||
|
msg, msg->data, msg->head);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ unsigned char *msg_push(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
msg->data -= len;
|
||||||
|
msg->len += len;
|
||||||
|
if(msg->data < msg->head)
|
||||||
|
{
|
||||||
|
eprint("msg_under_panic msg(%p) data(%p) head(%p)\n",
|
||||||
|
msg, msg->data, msg->head);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return msg->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static __inline__ unsigned char *__msg_pull(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = msg->data;
|
||||||
|
|
||||||
|
msg->len -= len;
|
||||||
|
msg->data += len;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ unsigned char * msg_pull(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
if (len > (unsigned int)msg->len)
|
||||||
|
return NULL;
|
||||||
|
return (unsigned char *)__msg_pull(msg,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ int msg_headroom(struct mbuffer *msg)
|
||||||
|
{
|
||||||
|
return msg->data - msg->head;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ int msg_tailroom(struct mbuffer *msg)
|
||||||
|
{
|
||||||
|
return msg->end-msg->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void msg_reserve(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
msg->data += len;
|
||||||
|
msg->tail += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void __msg_trim(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
msg->len = len;
|
||||||
|
msg->tail = msg->data + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void msg_trim(struct mbuffer *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
if ((unsigned int)msg->len > len) {
|
||||||
|
__msg_trim(msg, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,260 @@
|
||||||
|
/* mlayer3.h
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MLAYER3_H
|
||||||
|
#define _MLAYER3_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <mISDN/mISDNcompat.h>
|
||||||
|
|
||||||
|
struct l3_head {
|
||||||
|
unsigned char type;
|
||||||
|
unsigned char crlen;
|
||||||
|
unsigned short cr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct m_extie {
|
||||||
|
unsigned char ie;
|
||||||
|
unsigned char codeset;
|
||||||
|
unsigned char len;
|
||||||
|
unsigned char *val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l3_msg {
|
||||||
|
unsigned int type;
|
||||||
|
unsigned int pid;
|
||||||
|
unsigned char *bearer_capability; /* ie 0x04 pos 0 */
|
||||||
|
unsigned char *cause; /* ie 0x08 pos 1 */
|
||||||
|
unsigned char *call_id; /* ie 0x10 pos 2 */
|
||||||
|
unsigned char *call_state; /* ie 0x14 pos 3 */
|
||||||
|
unsigned char *channel_id; /* ie 0x18 pos 4 */
|
||||||
|
unsigned char *facility; /* ie 0x1c pos 5 */
|
||||||
|
unsigned char *progress; /* ie 0x1e pos 6 */
|
||||||
|
unsigned char *net_fac; /* ie 0x20 pos 7 */
|
||||||
|
unsigned char *notify; /* ie 0x27 pos 8 */
|
||||||
|
unsigned char *display; /* ie 0x28 pos 9 */
|
||||||
|
unsigned char *date; /* ie 0x29 pos 10 */
|
||||||
|
unsigned char *keypad; /* ie 0x2c pos 11 */
|
||||||
|
unsigned char *signal; /* ie 0x34 pos 12 */
|
||||||
|
unsigned char *info_rate; /* ie 0x40 pos 13 */
|
||||||
|
unsigned char *end2end_transit; /* ie 0x42 pos 14 */
|
||||||
|
unsigned char *transit_delay_sel; /* ie 0x43 pos 15 */
|
||||||
|
unsigned char *pktl_bin_para; /* ie 0x44 pos 16 */
|
||||||
|
unsigned char *pktl_window; /* ie 0x45 pos 17 */
|
||||||
|
unsigned char *pkt_size; /* ie 0x46 pos 18 */
|
||||||
|
unsigned char *closed_userg; /* ie 0x47 pos 19 */
|
||||||
|
unsigned char *reverse_charge; /* ie 0x4a pos 20 */
|
||||||
|
unsigned char *connected_nr; /* ie 0x4c pos 21 */
|
||||||
|
unsigned char *connected_sub; /* ie 0x4d pos 22 */
|
||||||
|
unsigned char *calling_nr; /* ie 0x6c pos 23 */
|
||||||
|
unsigned char *calling_sub; /* ie 0x6d pos 24 */
|
||||||
|
unsigned char *called_nr; /* ie 0x70 pos 25 */
|
||||||
|
unsigned char *called_sub; /* ie 0x71 pos 26 */
|
||||||
|
unsigned char *redirecting_nr; /* ie 0x74 pos 27 */
|
||||||
|
unsigned char *redirection_nr; /* ie 0x76 pos 28 */
|
||||||
|
unsigned char *transit_net_sel; /* ie 0x78 pos 29 */
|
||||||
|
unsigned char *restart_ind; /* ie 0x79 pos 30 */
|
||||||
|
unsigned char *llc; /* ie 0x7c pos 31 */
|
||||||
|
unsigned char *hlc; /* ie 0x7d pos 32 */
|
||||||
|
unsigned char *useruser; /* ie 0x7e pos 33 */
|
||||||
|
unsigned char comprehension_req;
|
||||||
|
unsigned char more_data;
|
||||||
|
unsigned char sending_complete;
|
||||||
|
unsigned char congestion_level;
|
||||||
|
struct m_extie extra[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mlayer3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* callback function to send and receive messages from and to layer3
|
||||||
|
* @parameter1 struct mlayer3 - identfy the layer3
|
||||||
|
* @parameter2 message type MT_ constants (Q931 and some private)
|
||||||
|
* @parameter3 PID (process identification) value to identify the target process
|
||||||
|
* @parameter4 optional layer3 message, if here are no special IE to deliver, use NULL
|
||||||
|
*/
|
||||||
|
typedef int (mlayer3_cb_t)(struct mlayer3 *, unsigned int, unsigned int, struct l3_msg *);
|
||||||
|
|
||||||
|
|
||||||
|
/* debug helper */
|
||||||
|
#define MISDN_LIBDEBUG_ERROR 1
|
||||||
|
#define MISDN_LIBDEBUG_WARN 2
|
||||||
|
#define MISDN_LIBDEBUG_INFO 3
|
||||||
|
#define MISDN_LIBDEBUG_DEBUG 4
|
||||||
|
|
||||||
|
typedef int (*mi_thread_create_t)(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *),
|
||||||
|
void *arg, const char *file, const char *caller, int line, const char *start_fn);
|
||||||
|
typedef int (*mi_debug_t)(const char *file, int line, const char *func, int level, const char *fmt, va_list va);
|
||||||
|
typedef void * (*mi_malloc_t)(size_t size, const char *file, int line, const char *func);
|
||||||
|
typedef void * (*mi_calloc_t)(size_t nmemb, size_t size, const char *file, int line, const char *func);
|
||||||
|
typedef void (*mi_free_t)(void *ptr, const char *file, int line, const char *func);
|
||||||
|
|
||||||
|
|
||||||
|
struct mi_ext_fn_s {
|
||||||
|
mi_thread_create_t thread_create;
|
||||||
|
mi_debug_t prt_debug;
|
||||||
|
mi_malloc_t malloc;
|
||||||
|
mi_calloc_t calloc;
|
||||||
|
mi_free_t reuse;
|
||||||
|
mi_free_t free;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct mi_ext_fn_s *mi_extern_func;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To avoid to include always all headers needed for mISDNif.h we redefine MISDN_CHMAP_SIZE here
|
||||||
|
* Please make sure to keep it in sync with mISDNif.h (but changes are very unlikely)
|
||||||
|
*/
|
||||||
|
#ifndef MISDN_CHMAP_SIZE
|
||||||
|
#define MISDN_MAX_CHANNEL 127
|
||||||
|
#define MISDN_CHMAP_SIZE ((MISDN_MAX_CHANNEL + 1) >> 3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mISDN_devinfo;
|
||||||
|
|
||||||
|
struct mlayer3 {
|
||||||
|
unsigned int device;
|
||||||
|
unsigned int nr_bchannel;
|
||||||
|
unsigned long options;
|
||||||
|
mlayer3_cb_t *to_layer3;
|
||||||
|
mlayer3_cb_t *from_layer3;
|
||||||
|
void *priv; /* free use for applications */
|
||||||
|
struct mISDN_devinfo *devinfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Layer3 protocols
|
||||||
|
*/
|
||||||
|
#define L3_PROTOCOL_DSS1_USER 0x101
|
||||||
|
#define L3_PROTOCOL_DSS1_NET 0x102
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Layer3 property Flags
|
||||||
|
*
|
||||||
|
* 16...31 reserved for internal use
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MISDN_FLG_PTP 1
|
||||||
|
#define MISDN_FLG_NET_HOLD 2
|
||||||
|
#define MISDN_FLG_L2_HOLD 3
|
||||||
|
#define MISDN_FLG_L2_CLEAN 4
|
||||||
|
#define MISDN_FLG_L1_HOLD 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Layer3 <----> Application additional message types
|
||||||
|
* Basic messages are coded like Q931 MT_ from q931.h
|
||||||
|
*/
|
||||||
|
/* Application <---> L3 */
|
||||||
|
#define MT_ASSIGN 0x11000
|
||||||
|
/* L3 ---> Application */
|
||||||
|
#define MT_FREE 0x11001
|
||||||
|
#define MT_L2ESTABLISH 0x12000
|
||||||
|
#define MT_L2RELEASE 0x12001
|
||||||
|
#define MT_L2IDLE 0x12002
|
||||||
|
#define MT_ERROR 0x18000
|
||||||
|
#define MT_TIMEOUT 0x18001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process IDs
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define MISDN_PID_DUMMY 0x81000000
|
||||||
|
#define MISDN_PID_GLOBAL 0x82000000
|
||||||
|
#define MISDN_PID_NONE 0xFFFFFFFF
|
||||||
|
#define MISDN_PID_MASTER 0xFF000000
|
||||||
|
#define MISDN_PID_CRTYPE_MASK 0xFF000000
|
||||||
|
#define MISDN_PID_CID_MASK 0x00FF0000
|
||||||
|
#define MISDN_PID_CR_MASK 0xFF00FFFF
|
||||||
|
#define MISDN_PID_CRVAL_MASK 0x0000FFFF
|
||||||
|
#define MISDN_PID_CR_FLAG 0x00008000
|
||||||
|
#define MISDN_CES_MASTER 0x0000FF00
|
||||||
|
|
||||||
|
#define MISDN_LIB_VERSION 2
|
||||||
|
#define MISDN_LIB_RELEASE 5
|
||||||
|
|
||||||
|
#define MISDN_LIB_INTERFACE ((MISDN_LIB_VERSION << 16) | MISDN_LIB_RELEASE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init layer3 statemachines and caches
|
||||||
|
* must be called before first open
|
||||||
|
* @parameter count of cached mbuffers
|
||||||
|
* @parameter optional block of external functions for debug
|
||||||
|
* @parameter use linke user space mISDN library instead of kernel socket
|
||||||
|
* @return: interface version
|
||||||
|
*/
|
||||||
|
extern unsigned int init_layer3(int, struct mi_ext_fn_s *, int user_space_misdn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup layer3 statemachines and chaches
|
||||||
|
* must be called after all layer3 are closed
|
||||||
|
*/
|
||||||
|
extern void cleanup_layer3(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open a layer3 stack
|
||||||
|
* @parameter1 - device id
|
||||||
|
* @parameter2 - protocol
|
||||||
|
* @parameter3 - layer3 additional properties
|
||||||
|
* @parameter4 - callback function to deliver messages
|
||||||
|
* @parameter5 - pointer for private application use
|
||||||
|
*/
|
||||||
|
extern struct mlayer3 *open_layer3(unsigned int, unsigned int, unsigned int, mlayer3_cb_t *, void *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close a layer3 stack
|
||||||
|
* parameter1 - stack struct
|
||||||
|
*/
|
||||||
|
extern void close_layer3(struct mlayer3 *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* run stack for one loop
|
||||||
|
* parameter1 - stack struct
|
||||||
|
*/
|
||||||
|
extern int work_layer3(struct mlayer3 *);
|
||||||
|
|
||||||
|
extern unsigned int request_new_pid(struct mlayer3 *);
|
||||||
|
extern int mISDN_get_pcm_slots(struct mlayer3 *, int, int *, int *);
|
||||||
|
extern int mISDN_set_pcm_slots(struct mlayer3 *, int, int, int);
|
||||||
|
extern int add_layer3_ie(struct l3_msg *, unsigned char, int, unsigned char *);
|
||||||
|
extern void l3_msg_increment_refcnt(struct l3_msg *);
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
extern struct l3_msg *__alloc_l3_msg(const char *file, int lineno, const char *func);
|
||||||
|
extern void __free_l3_msg(struct l3_msg *, const char *file, int lineno, const char *func);
|
||||||
|
|
||||||
|
#define alloc_l3_msg() __alloc_l3_msg(__FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
#define free_l3_msg(p) __free_l3_msg(p, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
extern struct l3_msg *alloc_l3_msg(void);
|
||||||
|
extern void free_l3_msg(struct l3_msg *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void mISDN_set_debug_level(unsigned int);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,363 @@
|
||||||
|
/* q931.h
|
||||||
|
*
|
||||||
|
* Basic Q931 defines
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _Q931_H
|
||||||
|
#define _Q931_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Q931 protocol discriminator
|
||||||
|
*/
|
||||||
|
#define Q931_PD 0x08
|
||||||
|
/*
|
||||||
|
* Q931 Message-Types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MT_ALERTING 0x01
|
||||||
|
#define MT_CALL_PROCEEDING 0x02
|
||||||
|
#define MT_CONNECT 0x07
|
||||||
|
#define MT_CONNECT_ACKNOWLEDGE 0x0f
|
||||||
|
#define MT_PROGRESS 0x03
|
||||||
|
#define MT_SETUP 0x05
|
||||||
|
#define MT_SETUP_ACKNOWLEDGE 0x0d
|
||||||
|
#define MT_RESUME 0x26
|
||||||
|
#define MT_RESUME_ACKNOWLEDGE 0x2e
|
||||||
|
#define MT_RESUME_REJECT 0x22
|
||||||
|
#define MT_SUSPEND 0x25
|
||||||
|
#define MT_SUSPEND_ACKNOWLEDGE 0x2d
|
||||||
|
#define MT_SUSPEND_REJECT 0x21
|
||||||
|
#define MT_USER_INFORMATION 0x20
|
||||||
|
#define MT_DISCONNECT 0x45
|
||||||
|
#define MT_RELEASE 0x4d
|
||||||
|
#define MT_RELEASE_COMPLETE 0x5a
|
||||||
|
#define MT_RESTART 0x46
|
||||||
|
#define MT_RESTART_ACKNOWLEDGE 0x4e
|
||||||
|
#define MT_SEGMENT 0x60
|
||||||
|
#define MT_CONGESTION_CONTROL 0x79
|
||||||
|
#define MT_INFORMATION 0x7b
|
||||||
|
#define MT_FACILITY 0x62
|
||||||
|
#define MT_NOTIFY 0x6e
|
||||||
|
#define MT_STATUS 0x7d
|
||||||
|
#define MT_STATUS_ENQUIRY 0x75
|
||||||
|
#define MT_HOLD 0x24
|
||||||
|
#define MT_HOLD_ACKNOWLEDGE 0x28
|
||||||
|
#define MT_HOLD_REJECT 0x30
|
||||||
|
#define MT_RETRIEVE 0x31
|
||||||
|
#define MT_RETRIEVE_ACKNOWLEDGE 0x33
|
||||||
|
#define MT_RETRIEVE_REJECT 0x37
|
||||||
|
#define MT_REGISTER 0x64
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Info Elements
|
||||||
|
*/
|
||||||
|
// not implemented
|
||||||
|
// #define IE_SEGMENT 0x00
|
||||||
|
#define IE_BEARER 0x04
|
||||||
|
#define IE_CAUSE 0x08
|
||||||
|
#define IE_CALL_ID 0x10
|
||||||
|
#define IE_CALL_STATE 0x14
|
||||||
|
#define IE_CHANNEL_ID 0x18
|
||||||
|
#define IE_FACILITY 0x1c
|
||||||
|
#define IE_PROGRESS 0x1e
|
||||||
|
#define IE_NET_FAC 0x20
|
||||||
|
#define IE_NOTIFY 0x27
|
||||||
|
#define IE_DISPLAY 0x28
|
||||||
|
#define IE_DATE 0x29
|
||||||
|
#define IE_KEYPAD 0x2c
|
||||||
|
#define IE_SIGNAL 0x34
|
||||||
|
#define IE_INFORATE 0x40
|
||||||
|
#define IE_E2E_TDELAY 0x42
|
||||||
|
#define IE_TDELAY_SEL 0x43
|
||||||
|
#define IE_PACK_BINPARA 0x44
|
||||||
|
#define IE_PACK_WINSIZE 0x45
|
||||||
|
#define IE_PACK_SIZE 0x46
|
||||||
|
#define IE_CUG 0x47
|
||||||
|
#define IE_REV_CHARGE 0x4a
|
||||||
|
#define IE_CONNECT_PN 0x4c
|
||||||
|
#define IE_CONNECT_SUB 0x4d
|
||||||
|
#define IE_CALLING_PN 0x6c
|
||||||
|
#define IE_CALLING_SUB 0x6d
|
||||||
|
#define IE_CALLED_PN 0x70
|
||||||
|
#define IE_CALLED_SUB 0x71
|
||||||
|
#define IE_REDIRECTING_NR 0x74
|
||||||
|
#define IE_REDIRECTION_NR 0x76
|
||||||
|
#define IE_TRANS_SEL 0x78
|
||||||
|
#define IE_RESTART_IND 0x79
|
||||||
|
#define IE_LLC 0x7c
|
||||||
|
#define IE_HLC 0x7d
|
||||||
|
#define IE_USER_USER 0x7e
|
||||||
|
|
||||||
|
#define IE_COUNT 34
|
||||||
|
|
||||||
|
// not implemented
|
||||||
|
#define IE_ESCAPE 0x7f
|
||||||
|
// one octet IE
|
||||||
|
#define IE_SHIFT 0x90
|
||||||
|
#define IE_MORE_DATA 0xa0
|
||||||
|
#define IE_COMPLETE 0xa1
|
||||||
|
#define IE_CONGESTION 0xb0
|
||||||
|
// not allowed for ETSI
|
||||||
|
#define IE_REPEAT 0xd0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* weight for IE in check lists
|
||||||
|
*/
|
||||||
|
#define IE_MANDATORY 0x0100
|
||||||
|
/* mandatory not in every case */
|
||||||
|
#define IE_MANDATORY_1 0x0200
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cause location
|
||||||
|
*/
|
||||||
|
#define CAUSE_LOC_USER 0
|
||||||
|
#define CAUSE_LOC_PRVN_LOCUSER 1
|
||||||
|
#define CAUSE_LOC_PUBN_LOCUSER 2
|
||||||
|
#define CAUSE_LOC_TRANSIT 3
|
||||||
|
#define CAUSE_LOC_PUBN_RMTUSER 4
|
||||||
|
#define CAUSE_LOC_PRVN_RMTUSER 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cause values
|
||||||
|
*/
|
||||||
|
#define CAUSE_UNASSIGNED_NUMBER 1
|
||||||
|
#define CAUSE_NO_TRANSIT_ROUTE 2
|
||||||
|
#define CAUSE_NO_ROUTE 3
|
||||||
|
#define CAUSE_CHANNEL_UNACCEPT 6
|
||||||
|
#define CAUSE_NORMAL_CLEARING 16
|
||||||
|
#define CAUSE_USER_BUSY 17
|
||||||
|
#define CAUSE_NOUSER_RESPONDING 18
|
||||||
|
#define CAUSE_ALERTED_NO_ANSWER 19
|
||||||
|
#define CAUSE_CALL_REJECTED 21
|
||||||
|
#define CAUSE_NONSELECTED_USER 26
|
||||||
|
#define CAUSE_DEST_OUT_OF_ORDER 27
|
||||||
|
#define CAUSE_INVALID_NUMBER 28
|
||||||
|
#define CAUSE_FACILITY_REJECTED 29
|
||||||
|
#define CAUSE_STATUS_RESPONSE 30
|
||||||
|
#define CAUSE_NORMALUNSPECIFIED 31
|
||||||
|
#define CAUSE_NO_CHANNEL 34
|
||||||
|
#define CAUSE_NET_OUT_OF_ORDER 28
|
||||||
|
#define CAUSE_TEMPORARY_FAILURE 41
|
||||||
|
#define CAUSE_SEQ_CONGESTION 42
|
||||||
|
#define CAUSE_REQUESTED_CHANNEL 44
|
||||||
|
#define CAUSE_RESOURCES_UNAVAIL 47
|
||||||
|
#define CAUSE_FACILITY_NOTSUBSCRIBED 50
|
||||||
|
#define CAUSE_FACILITY_NOTIMPLEMENTED 69
|
||||||
|
#define CAUSE_INVALID_CALLREF 81
|
||||||
|
#define CAUSE_INCOMPATIBLE_DEST 88
|
||||||
|
#define CAUSE_MANDATORY_IE_MISS 96
|
||||||
|
#define CAUSE_MT_NOTIMPLEMENTED 97
|
||||||
|
#define CAUSE_NOTCOMPAT_STATE_OR_MT_NOTIMPLEMENTED 98
|
||||||
|
#define CAUSE_IE_NOTIMPLEMENTED 99
|
||||||
|
#define CAUSE_INVALID_CONTENTS 100
|
||||||
|
#define CAUSE_NOTCOMPAT_STATE 101
|
||||||
|
#define CAUSE_TIMER_EXPIRED 102
|
||||||
|
#define CAUSE_PROTOCOL_ERROR 111
|
||||||
|
|
||||||
|
#define NO_CAUSE 254
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restart indication class values
|
||||||
|
*/
|
||||||
|
#define RESTART_CLASS_CHANNEL 0
|
||||||
|
#define RESTART_CLASS_SINGLE 6
|
||||||
|
#define RESTART_CLASS_ALL 7
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parser error codes
|
||||||
|
*/
|
||||||
|
#define Q931_ERROR_LEN 0x010000
|
||||||
|
#define Q931_ERROR_OVERFLOW 0x020000
|
||||||
|
#define Q931_ERROR_CREF 0x040000
|
||||||
|
#define Q931_ERROR_FATAL 0x0F0000
|
||||||
|
#define Q931_ERROR_IELEN 0x100000
|
||||||
|
#define Q931_ERROR_UNKNOWN 0x200000
|
||||||
|
#define Q931_ERROR_COMPREH 0x400000
|
||||||
|
#define Q931_ERROR_IESEQ 0x800000 /* do not care in our implementation */
|
||||||
|
|
||||||
|
/* Bearer capability */
|
||||||
|
#define Q931_CAP_SPEECH 0x00
|
||||||
|
#define Q931_CAP_UNRES_DIGITAL 0x08
|
||||||
|
#define Q931_CAP_RES_DIGITAL 0x09
|
||||||
|
#define Q931_CAP_3KHZ_AUDIO 0x10
|
||||||
|
#define Q931_CAP_7KHZ_AUDIO 0x11
|
||||||
|
#define Q931_CAP_VIDEO 0x18
|
||||||
|
|
||||||
|
/* Bearer L1 user info */
|
||||||
|
#define Q931_L1INFO_V110 0x01
|
||||||
|
#define Q931_L1INFO_ULAW 0x02
|
||||||
|
#define Q931_L1INFO_ALAW 0x03
|
||||||
|
#define Q931_L1INFO_G721 0x04
|
||||||
|
#define Q931_L1INFO_G722_5 0x05
|
||||||
|
#define Q931_L1INFO_G7XX_VIDEO 0x06
|
||||||
|
#define Q931_L1INFO_NONE_CCITT 0x07
|
||||||
|
#define Q931_L1INFO_V120 0x08
|
||||||
|
#define Q931_L1INFO_X31 0x09
|
||||||
|
|
||||||
|
struct misdn_channel_info {
|
||||||
|
unsigned char nr; /* channel number/slot or special */
|
||||||
|
unsigned char flags; /* exclusiv, not Basic, ANY, NONE */
|
||||||
|
unsigned char type; /* B-channel, D-channel, H0, H11, H12 */
|
||||||
|
unsigned char ctrl; /* Allocated, updated, needsend, sent */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* special channel number defines
|
||||||
|
*/
|
||||||
|
#define MI_CHAN_ANY 0xff
|
||||||
|
#define MI_CHAN_NONE 0xfe
|
||||||
|
#define MI_CHAN_DCHANNEL 0xfd
|
||||||
|
|
||||||
|
#define MI_CHAN_FLG_NONE 0x01
|
||||||
|
#define MI_CHAN_FLG_ANY 0x02
|
||||||
|
#define MI_CHAN_FLG_DCHANNEL 0x04
|
||||||
|
#define MI_CHAN_FLG_EXCLUSIVE 0x08
|
||||||
|
#define MI_CHAN_FLG_OTHER_IF 0x20
|
||||||
|
|
||||||
|
#define MI_CHAN_TYP_NONE 0
|
||||||
|
#define MI_CHAN_TYP_B 1
|
||||||
|
#define MI_CHAN_TYP_D 2
|
||||||
|
#define MI_CHAN_TYP_H0 3
|
||||||
|
#define MI_CHAN_TYP_H11 4
|
||||||
|
#define MI_CHAN_TYP_H12 5
|
||||||
|
|
||||||
|
#define MI_CHAN_CTRL_UPDATED 0x01
|
||||||
|
#define MI_CHAN_CTRL_NEEDSEND 0x02
|
||||||
|
#define MI_CHAN_CTRL_SENT 0x04
|
||||||
|
#define MI_CHAN_CTRL_ALLOCATED 0x10
|
||||||
|
#define MI_CHAN_CTRL_DOWN 0x20
|
||||||
|
|
||||||
|
/* progress info */
|
||||||
|
struct misdn_progress_info {
|
||||||
|
unsigned char loc; /* location, octet 3 */
|
||||||
|
unsigned char desc; /* description, octet 3 */
|
||||||
|
unsigned char resv; /* reserved */
|
||||||
|
unsigned char ctrl; /* ctrl info flags */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Q931 location
|
||||||
|
*/
|
||||||
|
#define Q931_LOC_USER 0
|
||||||
|
#define Q931_LOC_PRVN_LOCUSER 1
|
||||||
|
#define Q931_LOC_PUBN_LOCUSER 2
|
||||||
|
#define Q931_LOC_PUBN_RMTUSER 4
|
||||||
|
#define Q931_LOC_PRVN_RMTUSER 5
|
||||||
|
#define Q931_LOC_INTERNATIONAL 7
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Progress values
|
||||||
|
*/
|
||||||
|
#define PROGRESS_NOT_E2E_ISDN 1
|
||||||
|
#define PROGRESS_DEST_NOT_ISDN 2
|
||||||
|
#define PROGRESS_ORIG_NOT_ISDN 3
|
||||||
|
#define PROGRESS_RET_TO_ISDN 4
|
||||||
|
#define PROGRESS_INBAND 8
|
||||||
|
|
||||||
|
/* Progress control flags */
|
||||||
|
#define MI_PROG_CTRL_UPDATED 0x01
|
||||||
|
#define MI_PROG_CTRL_NEEDSEND 0x02
|
||||||
|
#define MI_PROG_CTRL_SENT 0x04
|
||||||
|
|
||||||
|
/* Reason for diversion */
|
||||||
|
#define MI_DIV_REASON_UNKNOWN 0x00
|
||||||
|
#define MI_DIV_REASON_CFB 0x01
|
||||||
|
#define MI_DIV_REASON_CFNR 0x02
|
||||||
|
#define MI_DIV_REASON_CD 0x0a
|
||||||
|
#define MI_DIV_REASON_CFU 0x0f
|
||||||
|
|
||||||
|
/* Number qualifiers */
|
||||||
|
#define Q931_NTYPE_UNKNOWN 0
|
||||||
|
#define Q931_NTYPE_INTERNATIONAL 1
|
||||||
|
#define Q931_NTYPE_NATIONAL 2
|
||||||
|
#define Q931_NTYPE_NETWORKSPECIFIC 3
|
||||||
|
#define Q931_NTYPE_SUBSCRIBER 4
|
||||||
|
#define Q931_NTYPE_ABBREVIATED 6
|
||||||
|
#define Q931_NTYPE_RESERVED 7
|
||||||
|
|
||||||
|
#define Q931_NPLAN_UNKNOWN 0x0
|
||||||
|
#define Q931_NPLAN_ISDN 0x1
|
||||||
|
#define Q931_NPLAN_DATA 0x3
|
||||||
|
#define Q931_NPLAN_TELEX 0x4
|
||||||
|
#define Q931_NPLAN_NATIONAL 0x8
|
||||||
|
#define Q931_NPLAN_PRIVATE 0x9
|
||||||
|
#define Q931_NPLAN_RESERVED 0xf
|
||||||
|
|
||||||
|
#define Q931_NPRESENTATION_ALLOWED 0
|
||||||
|
#define Q931_NPRESENTATION_RESTRICTED 1
|
||||||
|
#define Q931_NPRESENTATION_NOTAVAILABLE 2
|
||||||
|
#define Q931_NPRESENTATION_RESERVED 3
|
||||||
|
|
||||||
|
#define Q931_NSCREEN_USER_NOT 0
|
||||||
|
#define Q931_NSCREEN_USER_PASSED 1
|
||||||
|
#define Q931_NSCREEN_USER_FAILED 2
|
||||||
|
#define Q931_NSCREEN_NETWORK 3
|
||||||
|
|
||||||
|
/* Common IE encode helpers */
|
||||||
|
struct l3_msg;
|
||||||
|
struct asn1_parm;
|
||||||
|
|
||||||
|
extern int l3_ie2pos(unsigned char);
|
||||||
|
|
||||||
|
extern int mi_encode_bearer(struct l3_msg *, unsigned int, unsigned int, unsigned int, unsigned int);
|
||||||
|
extern int mi_encode_hlc(struct l3_msg *, int, int);
|
||||||
|
extern int mi_encode_channel_id(struct l3_msg *, struct misdn_channel_info *);
|
||||||
|
extern int mi_encode_calling_nr(struct l3_msg *, char *, int, unsigned int, unsigned int, unsigned int);
|
||||||
|
extern int mi_encode_connected_nr(struct l3_msg *, char *, int, unsigned int, unsigned int, unsigned int);
|
||||||
|
extern int mi_encode_called_nr(struct l3_msg *, char *, unsigned int, unsigned int);
|
||||||
|
extern int mi_encode_redirecting_nr(struct l3_msg *, char *, int, unsigned int, unsigned int, int);
|
||||||
|
extern int mi_encode_redirection_nr(struct l3_msg *, char *, int, unsigned int, unsigned int);
|
||||||
|
extern int mi_encode_useruser(struct l3_msg *, int, int, char *);
|
||||||
|
extern int mi_encode_cause(struct l3_msg *l, int cause, int, int, unsigned char *);
|
||||||
|
extern int mi_encode_progress(struct l3_msg *, struct misdn_progress_info *);
|
||||||
|
extern int mi_encode_date(struct l3_msg *, struct tm *);
|
||||||
|
extern int mi_encode_restart_ind(struct l3_msg *, unsigned char);
|
||||||
|
extern int mi_encode_facility(struct l3_msg *, struct asn1_parm *);
|
||||||
|
extern int mi_encode_notification_ind(struct l3_msg *, int);
|
||||||
|
|
||||||
|
/* Common IE decode helpers */
|
||||||
|
struct mbuffer;
|
||||||
|
extern int parseQ931(struct mbuffer *);
|
||||||
|
extern int l3_ie2pos(u_char);
|
||||||
|
extern unsigned char l3_pos2ie(int);
|
||||||
|
|
||||||
|
extern int mi_decode_progress(struct l3_msg *, struct misdn_progress_info *);
|
||||||
|
extern int mi_decode_bearer_capability(struct l3_msg *, int *, int *, int *, int *, int *,
|
||||||
|
int *, int *, int *, int *, int *, int *, int *, int *);
|
||||||
|
extern int mi_decode_hlc(struct l3_msg *l3m, int *, int *);
|
||||||
|
extern int mi_decode_cause(struct l3_msg *, int *, int *, int *, int *, int *, unsigned char *);
|
||||||
|
extern int mi_decode_channel_id(struct l3_msg *, struct misdn_channel_info *);
|
||||||
|
extern int mi_decode_calling_nr(struct l3_msg *, int *, int *, int *, int *, char *);
|
||||||
|
extern int mi_decode_connected_nr(struct l3_msg *, int *, int *, int *, int *, char *);
|
||||||
|
extern int mi_decode_called_nr(struct l3_msg *, int *, int *, char *);
|
||||||
|
extern int mi_decode_redirecting_nr(struct l3_msg *, int *, int *, int *, int *, int *, char *);
|
||||||
|
extern int mi_decode_redirection_nr(struct l3_msg *, int *, int *, int *, char *);
|
||||||
|
extern int mi_decode_display(struct l3_msg *, char *, int);
|
||||||
|
extern int mi_decode_useruser(struct l3_msg *, int *, int *, char *, int);
|
||||||
|
extern int mi_decode_date(struct l3_msg *, struct tm *);
|
||||||
|
extern int mi_decode_restart_ind(struct l3_msg *, unsigned char *);
|
||||||
|
extern int mi_decode_facility(struct l3_msg *, struct asn1_parm *);
|
||||||
|
extern int mi_decode_notification_ind(struct l3_msg *, int*);
|
||||||
|
|
||||||
|
/* some print helpers */
|
||||||
|
extern const char *mi_bearer2str(int);
|
||||||
|
extern const char *mi_msg_type2str(unsigned int);
|
||||||
|
extern const char *_mi_msg_type2str(unsigned int);
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,119 @@
|
||||||
|
/* mlist.h
|
||||||
|
*
|
||||||
|
* Simple doubly linked list implementation and helper
|
||||||
|
* function reduce version of linux kernel list.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MLIST_H
|
||||||
|
#define _MLIST_H
|
||||||
|
|
||||||
|
struct list_head {
|
||||||
|
struct list_head *next, *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||||
|
|
||||||
|
#define LIST_HEAD(name) \
|
||||||
|
struct list_head name = LIST_HEAD_INIT(name)
|
||||||
|
|
||||||
|
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||||
|
{
|
||||||
|
list->next = list;
|
||||||
|
list->prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_add_head - add a new entry on the top
|
||||||
|
* @new: new entry to be added
|
||||||
|
* @head: list head to add it after
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void list_add_head(struct list_head *new, struct list_head *head)
|
||||||
|
{
|
||||||
|
head->next->prev = new;
|
||||||
|
new->next = head->next;
|
||||||
|
new->prev = head;
|
||||||
|
head->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_add_tail - add a new entry
|
||||||
|
* @new: new entry to be added
|
||||||
|
* @head: list head to add it before
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||||
|
{
|
||||||
|
head->prev->next = new;
|
||||||
|
new->next = head;
|
||||||
|
new->prev = head->prev;
|
||||||
|
head->prev = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LIST_POISON1 0xdeadbee1
|
||||||
|
#define LIST_POISON2 0xdeadbee2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_del - deletes entry from list.
|
||||||
|
* @entry: the element to delete from the list.
|
||||||
|
*/
|
||||||
|
static inline void list_del(struct list_head *entry)
|
||||||
|
{
|
||||||
|
entry->next->prev = entry->prev;
|
||||||
|
entry->prev->next = entry->next;
|
||||||
|
entry->next = (void *)LIST_POISON1;
|
||||||
|
entry->prev = (void *)LIST_POISON2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_empty - tests whether a list is empty
|
||||||
|
* @head: the list to test.
|
||||||
|
*/
|
||||||
|
static inline int list_empty(const struct list_head *head)
|
||||||
|
{
|
||||||
|
return head->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_entry - get the struct for this entry
|
||||||
|
* @ptr: the &struct list_head pointer.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define list_entry(ptr, type, member) \
|
||||||
|
container_of(ptr, type, member)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_for_each - iterate over a list
|
||||||
|
* @pos: the &struct list_head to use as a loop counter.
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); \
|
||||||
|
pos = pos->next)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* list_for_each_entry - iterate over list of given type
|
||||||
|
* @pos: the type * to use as a loop counter.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry(pos, head, member) \
|
||||||
|
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||||
|
* @pos: the type * to use as a loop counter.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||||
|
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||||
|
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* mtimer.h
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MTIMER_H
|
||||||
|
#define MTIMER_H
|
||||||
|
|
||||||
|
#include "mlist.h"
|
||||||
|
|
||||||
|
typedef void (mtimer_func_t)(void *);
|
||||||
|
|
||||||
|
struct timer_base {
|
||||||
|
struct list_head pending_timer;
|
||||||
|
int tdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mtimer {
|
||||||
|
struct list_head list;
|
||||||
|
struct timer_base *tb;
|
||||||
|
int id;
|
||||||
|
double expires;
|
||||||
|
int timeout;
|
||||||
|
void *data;
|
||||||
|
mtimer_func_t *function;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int init_timer(struct mtimer *, struct timer_base *, void *, mtimer_func_t *);
|
||||||
|
extern int add_timer(struct mtimer *, int);
|
||||||
|
extern int del_timer(struct mtimer *);
|
||||||
|
extern int timer_pending(struct mtimer *);
|
||||||
|
extern int expire_timer(struct timer_base *, int);
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,386 @@
|
||||||
|
/* mlayer3.c
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
* Copyright 2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <mISDN/mlayer3.h>
|
||||||
|
#include <mISDN/mbuffer.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "helper.h"
|
||||||
|
#include "layer3.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include <mISDN/af_isdn.h>
|
||||||
|
#include "../../libmisdn/socket.h"
|
||||||
|
|
||||||
|
static int __init_done = 0;
|
||||||
|
|
||||||
|
static int user_space_misdn = 0;
|
||||||
|
|
||||||
|
struct mi_ext_fn_s *mi_extern_func;
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
init_layer3(int nr, struct mi_ext_fn_s *fn, int _user_space_misdn)
|
||||||
|
{
|
||||||
|
user_space_misdn = _user_space_misdn;
|
||||||
|
init_mbuffer(nr);
|
||||||
|
mISDNl3New();
|
||||||
|
__init_done = 1;
|
||||||
|
mI_debug_mask = 0;
|
||||||
|
if (fn)
|
||||||
|
mi_extern_func = fn;
|
||||||
|
else
|
||||||
|
mi_extern_func = NULL;
|
||||||
|
return MISDN_LIB_INTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup_layer3(void)
|
||||||
|
{
|
||||||
|
cleanup_mbuffer();
|
||||||
|
mISDNl3Free();
|
||||||
|
__init_done = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for now, maybe get this via some register prortocol in future */
|
||||||
|
extern struct l3protocol dss1user;
|
||||||
|
extern struct l3protocol dss1net;
|
||||||
|
/*
|
||||||
|
* open a layer3 stack
|
||||||
|
* parameter1 - device id
|
||||||
|
* parameter2 - protocol
|
||||||
|
* parameter3 - layer3 additional properties
|
||||||
|
* parameter4 - callback function to deliver messages
|
||||||
|
* parameter5 - pointer for private application use
|
||||||
|
*/
|
||||||
|
struct mlayer3 *
|
||||||
|
open_layer3(unsigned int dev, unsigned int proto, unsigned int prop, mlayer3_cb_t *f, void *p)
|
||||||
|
{
|
||||||
|
struct _layer3 *l3 = NULL;
|
||||||
|
int fd = 0, ret;
|
||||||
|
struct mISDNversion ver;
|
||||||
|
int set = 1;
|
||||||
|
void *mui;
|
||||||
|
u_int cnt;
|
||||||
|
|
||||||
|
if (__init_done == 0) {
|
||||||
|
eprint("You should call init_layer3(nr of message cache entres) first\n");
|
||||||
|
init_layer3(10, NULL, user_space_misdn);
|
||||||
|
}
|
||||||
|
if (user_space_misdn) {
|
||||||
|
ret = mISDN_base_create(&mui, ISDN_P_BASE);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not user space mISDN: %s\n", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = mISDN_base_ioctl(mui, IMGETVERSION, &ver);
|
||||||
|
} else {
|
||||||
|
fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
|
||||||
|
if (fd < 0) {
|
||||||
|
eprint("could not open socket: %s\n", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = ioctl(fd, IMGETVERSION, &ver);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not send IOCTL IMGETVERSION %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ver.release & MISDN_GIT_RELEASE)
|
||||||
|
iprint("mISDN kernel version %d.%02d.%d (git.misdn.eu) found\n", ver.major, ver.minor, ver.release & ~MISDN_GIT_RELEASE);
|
||||||
|
else
|
||||||
|
iprint("mISDN kernel version %d.%02d.%d found\n", ver.major, ver.minor, ver.release);
|
||||||
|
iprint("mISDN user version %d.%02d.%d found\n", MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
|
||||||
|
iprint("mISDN library interface version %d release %d\n", MISDN_LIB_VERSION, MISDN_LIB_RELEASE);
|
||||||
|
|
||||||
|
if (ver.major != MISDN_MAJOR_VERSION) {
|
||||||
|
eprint("VERSION incompatible please update\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* handle version backward compatibility specific stuff here */
|
||||||
|
|
||||||
|
if (mui)
|
||||||
|
ret = mISDN_base_ioctl(mui, IMGETCOUNT, &cnt);
|
||||||
|
if (fd)
|
||||||
|
ret = ioctl(fd, IMGETCOUNT, &cnt);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not send IOCTL IMGETCOUNT %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (cnt <= dev) {
|
||||||
|
eprint("Given device ID '%d' does not exist, there are '%d' devices.\n", dev, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
l3 = calloc(1, sizeof(struct _layer3));
|
||||||
|
if (!l3) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
l3->ml3.devinfo = calloc(1, sizeof(*l3->ml3.devinfo));
|
||||||
|
if (!l3->ml3.devinfo) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
l3->ml3.options = prop;
|
||||||
|
l3->ml3.from_layer3 = f;
|
||||||
|
l3->ml3.priv = p;
|
||||||
|
|
||||||
|
init_l3(l3);
|
||||||
|
l3->ml3.devinfo->id = dev;
|
||||||
|
if (mui)
|
||||||
|
ret = mISDN_base_ioctl(mui, IMGETDEVINFO, l3->ml3.devinfo);
|
||||||
|
if (fd)
|
||||||
|
ret = ioctl(fd, IMGETDEVINFO, l3->ml3.devinfo);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not send IOCTL IMGETDEVINFO %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (mui) {
|
||||||
|
mISDN_base_release(mui);
|
||||||
|
mui = NULL;
|
||||||
|
}
|
||||||
|
if (fd) {
|
||||||
|
close(fd);
|
||||||
|
fd = 0;
|
||||||
|
}
|
||||||
|
l3->ml3.nr_bchannel = l3->ml3.devinfo->nrbchan;
|
||||||
|
if (!(l3->ml3.devinfo->Dprotocols & (1 << ISDN_P_TE_E1))
|
||||||
|
&& !(l3->ml3.devinfo->Dprotocols & (1 << ISDN_P_NT_E1)))
|
||||||
|
test_and_set_bit(FLG_BASICRATE, &l3->ml3.options);
|
||||||
|
switch(proto) {
|
||||||
|
case L3_PROTOCOL_DSS1_USER:
|
||||||
|
if (!(l3->ml3.devinfo->Dprotocols & (1 << ISDN_P_TE_S0))
|
||||||
|
&& !(l3->ml3.devinfo->Dprotocols & (1 << ISDN_P_TE_E1))) {
|
||||||
|
eprint("protocol L3_PROTOCOL_DSS1_USER device do not support ISDN_P_TE_S0 / ISDN_P_TE_E1\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (user_space_misdn) {
|
||||||
|
ret = mISDN_data_create(&mui, ISDN_P_LAPD_TE);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not open ISDN_P_LAPD_TE protocol %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE);
|
||||||
|
if (fd < 0) {
|
||||||
|
eprint("could not open ISDN_P_LAPD_TE protocol %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dss1user.init(l3);
|
||||||
|
break;
|
||||||
|
case L3_PROTOCOL_DSS1_NET:
|
||||||
|
if (!(l3->ml3.devinfo->Dprotocols & (1 << ISDN_P_NT_S0))
|
||||||
|
&& !(l3->ml3.devinfo->Dprotocols & (1 << ISDN_P_NT_E1))) {
|
||||||
|
eprint("protocol L3_PROTOCOL_DSS1_NET device do not support ISDN_P_NT_S0 / ISDN_P_NT_E1\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (user_space_misdn) {
|
||||||
|
ret = mISDN_data_create(&mui, ISDN_P_LAPD_NT);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not open ISDN_P_LAPD_NT protocol %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_NT);
|
||||||
|
if (fd < 0) {
|
||||||
|
eprint("could not open ISDN_P_LAPD_NT protocol %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dss1net.init(l3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
eprint("protocol %x not supported\n", proto);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
l3->l2master.l2addr.family = AF_ISDN;
|
||||||
|
l3->l2master.l2addr.dev = dev;
|
||||||
|
l3->l2master.l2addr.channel = 0;
|
||||||
|
l3->l2master.l2addr.sapi = 0;
|
||||||
|
if (test_bit(MISDN_FLG_PTP, &l3->ml3.options))
|
||||||
|
l3->l2master.l2addr.tei = 0;
|
||||||
|
else
|
||||||
|
l3->l2master.l2addr.tei = 127;
|
||||||
|
if (mui)
|
||||||
|
ret = mISDN_data_bind(mui, (struct sockaddr *)&l3->l2master.l2addr, sizeof(l3->l2master.l2addr));
|
||||||
|
if (fd)
|
||||||
|
ret = bind(fd, (struct sockaddr *)&l3->l2master.l2addr, sizeof(l3->l2master.l2addr));
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not bind socket for device %d:%s\n", dev, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (test_bit(MISDN_FLG_L2_CLEAN, &l3->ml3.options)
|
||||||
|
&& proto == L3_PROTOCOL_DSS1_NET) {
|
||||||
|
if (mui)
|
||||||
|
ret = mISDN_data_ioctl(mui, IMCLEAR_L2, &set);
|
||||||
|
if (fd)
|
||||||
|
ret = ioctl(fd, IMCLEAR_L2, &set);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not send IOCTL IMCLEAN_L2 %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (test_bit(MISDN_FLG_L1_HOLD, &l3->ml3.options)) {
|
||||||
|
if (mui)
|
||||||
|
ret = mISDN_data_ioctl(mui, IMHOLD_L1, &set);
|
||||||
|
if (fd)
|
||||||
|
ret = ioctl(fd, IMHOLD_L1, &set);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not send IOCTL IMHOLD_L1 %s\n", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l3->l2inst = mui;
|
||||||
|
l3->l2sock = fd;
|
||||||
|
if (!user_space_misdn) {
|
||||||
|
l3->tbase.tdev = open("/dev/mISDNtimer", O_RDWR);
|
||||||
|
if (l3->tbase.tdev < 0) {
|
||||||
|
eprint("could not open /dev/mISDNtimer %s\n", strerror(errno));
|
||||||
|
eprint("It seems that you don't use udev filesystem. You may use this workarround:\n\n");
|
||||||
|
eprint("Do 'cat /proc/misc' and see the number in front of 'mISDNtimer'.\n");
|
||||||
|
eprint("Do 'mknod /dev/mISDNtimer c 10 xx', where xx is the number you saw.\n");
|
||||||
|
eprint("Note: This number changes if you load modules in different order, that use misc device.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (l3->l2sock < l3->tbase.tdev)
|
||||||
|
l3->maxfd = l3->tbase.tdev;
|
||||||
|
else
|
||||||
|
l3->maxfd = l3->l2sock;
|
||||||
|
}
|
||||||
|
if (!user_space_misdn) {
|
||||||
|
ret = l3_start(l3);
|
||||||
|
if (ret < 0) {
|
||||||
|
eprint("could not start layer3 thread for device %d\n", dev);
|
||||||
|
close(l3->tbase.tdev);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(&l3->ml3);
|
||||||
|
fail:
|
||||||
|
if (mui)
|
||||||
|
mISDN_base_release(mui);
|
||||||
|
if (fd)
|
||||||
|
close(fd);
|
||||||
|
if (l3) {
|
||||||
|
release_l3(l3);
|
||||||
|
if (l3->ml3.devinfo)
|
||||||
|
free(l3->ml3.devinfo);
|
||||||
|
free(l3);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close a layer3 stack
|
||||||
|
* parameter1 - stack struct
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
close_layer3(struct mlayer3 *ml3)
|
||||||
|
{
|
||||||
|
struct _layer3 *l3;
|
||||||
|
|
||||||
|
l3 = container_of(ml3, struct _layer3, ml3);
|
||||||
|
if (l3->l2sock)
|
||||||
|
l3_stop(l3);
|
||||||
|
if (l3->l2inst)
|
||||||
|
mISDN_base_release(l3->l2inst);
|
||||||
|
if (l3->l2sock)
|
||||||
|
close(l3->l2sock);
|
||||||
|
if (!user_space_misdn)
|
||||||
|
close(l3->tbase.tdev);
|
||||||
|
release_l3(l3);
|
||||||
|
if (ml3->devinfo)
|
||||||
|
free(ml3->devinfo);
|
||||||
|
free(l3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
work_layer3(struct mlayer3 *ml3)
|
||||||
|
{
|
||||||
|
struct _layer3 *l3;
|
||||||
|
|
||||||
|
l3 = container_of(ml3, struct _layer3, ml3);
|
||||||
|
return layer3_work(l3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mISDN_set_pcm_slots(struct mlayer3 *ml3, int channel, int tx, int rx)
|
||||||
|
{
|
||||||
|
/* need to be reimplemented */
|
||||||
|
#ifdef MISDN_CTRL_SET_PCM_SLOTS
|
||||||
|
struct _layer3 *l3;
|
||||||
|
struct mISDN_ctrl_req ctrlrq;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ctrlrq.op = MISDN_CTRL_SET_PCM_SLOTS;
|
||||||
|
ctrlrq.channel = 0; /* via D-channel */
|
||||||
|
ctrlrq.p1 = channel;
|
||||||
|
ctrlrq.p2 = tx;
|
||||||
|
ctrlrq.p3 = rx;
|
||||||
|
l3 = container_of(ml3, struct _layer3, ml3);
|
||||||
|
if (l3->l2inst)
|
||||||
|
ret = mISDN_data_ioctl(l3->l2inst, IMCTRLREQ, &ctrlrq);
|
||||||
|
if (l3->l2sock)
|
||||||
|
ret = ioctl(l3->l2sock, IMCTRLREQ, &ctrlrq);
|
||||||
|
if (ret < 0)
|
||||||
|
eprint("could not send IOCTL IMCTRLREQ %s\n", strerror(errno));
|
||||||
|
#else
|
||||||
|
int ret = -EOPNOTSUPP;
|
||||||
|
|
||||||
|
eprint("%s not supported in this version\n", __func__);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mISDN_get_pcm_slots(struct mlayer3 *ml3, int channel, int *txp, int *rxp)
|
||||||
|
{
|
||||||
|
#ifdef MISDN_CTRL_GET_PCM_SLOTS
|
||||||
|
struct _layer3 *l3;
|
||||||
|
struct mISDN_ctrl_req ctrlrq;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ctrlrq.op = MISDN_CTRL_GET_PCM_SLOTS;
|
||||||
|
ctrlrq.channel = 0; /* via D-channel */
|
||||||
|
ctrlrq.p1 = channel;
|
||||||
|
l3 = container_of(ml3, struct _layer3, ml3);
|
||||||
|
if (l3->l2inst)
|
||||||
|
ret = mISDN_data_ioctl(l3->l2inst, IMCTRLREQ, &ctrlrq);
|
||||||
|
if (l3->l2sock)
|
||||||
|
ret = ioctl(l3->l2sock, IMCTRLREQ, &ctrlrq);
|
||||||
|
if (ret < 0)
|
||||||
|
eprint("could not send IOCTL IMCTRLREQ %s\n", strerror(errno));
|
||||||
|
else {
|
||||||
|
if (txp)
|
||||||
|
*txp = ctrlrq.p2;
|
||||||
|
if (rxp)
|
||||||
|
*rxp = ctrlrq.p3;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int ret = -EOPNOTSUPP;
|
||||||
|
|
||||||
|
eprint("%s not supported in this version\n", __func__);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,162 @@
|
||||||
|
/* debug.c
|
||||||
|
*
|
||||||
|
* mISDN lib debug functions
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
* Copyright 2009, 2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "debug.h"
|
||||||
|
#include <mISDN/mlayer3.h>
|
||||||
|
|
||||||
|
unsigned int mI_debug_mask;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
|
||||||
|
#undef malloc
|
||||||
|
#undef calloc
|
||||||
|
#undef free
|
||||||
|
|
||||||
|
void *
|
||||||
|
__mi_alloc(size_t size, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (mi_extern_func && mi_extern_func->malloc)
|
||||||
|
p = mi_extern_func->malloc(size, file, lineno, func);
|
||||||
|
else
|
||||||
|
p = malloc(size);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
__mi_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (mi_extern_func && mi_extern_func->calloc)
|
||||||
|
p = mi_extern_func->calloc(nmemb, size, file, lineno, func);
|
||||||
|
else
|
||||||
|
p = calloc(nmemb, size);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__mi_free(void *ptr, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
if (mi_extern_func && mi_extern_func->free)
|
||||||
|
mi_extern_func->free(ptr, file, lineno, func);
|
||||||
|
else
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __mi_reuse(void *ptr, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
if (mi_extern_func && mi_extern_func->reuse)
|
||||||
|
mi_extern_func->reuse(ptr, file, lineno, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mISDN_set_debug_level(unsigned int mask)
|
||||||
|
{
|
||||||
|
mI_debug_mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mi_printf(const char *file, int line, const char *func, int lev, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
if (mi_extern_func && mi_extern_func->prt_debug) {
|
||||||
|
ret = mi_extern_func->prt_debug(file, line, func, lev, fmt, args);
|
||||||
|
} else {
|
||||||
|
FILE *f = stderr;
|
||||||
|
|
||||||
|
if (lev == MISDN_LIBDEBUG_DEBUG || lev == MISDN_LIBDEBUG_INFO)
|
||||||
|
f = stdout;
|
||||||
|
ret = vfprintf(f, fmt, args);
|
||||||
|
fflush(f);
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_mi_thread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *),
|
||||||
|
void *arg, const char *file, const char *caller, int line, const char *start_fn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (mi_extern_func && mi_extern_func->thread_create)
|
||||||
|
ret = mi_extern_func->thread_create(thread, attr, start_routine, arg, file, caller, line, start_fn);
|
||||||
|
else
|
||||||
|
ret = pthread_create(thread, attr, start_routine, arg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mi_dhexprint(const char *file, int line, const char *func, const char *head, unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *p,*obuf;
|
||||||
|
|
||||||
|
|
||||||
|
obuf = malloc(100);
|
||||||
|
if (!obuf)
|
||||||
|
return;
|
||||||
|
p = obuf;
|
||||||
|
*p = 0;
|
||||||
|
for (i = 1; i <= len; i++) {
|
||||||
|
p += sprintf(p, "%02x ", *buf);
|
||||||
|
buf++;
|
||||||
|
if (!(i % 32)) {
|
||||||
|
p--;
|
||||||
|
*p = 0;
|
||||||
|
mi_printf(file, line, func, MISDN_LIBDEBUG_DEBUG, "%s %s\n", head, obuf);
|
||||||
|
p = obuf;
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*obuf) {
|
||||||
|
p--;
|
||||||
|
*p = 0;
|
||||||
|
mi_printf(file, line, func, MISDN_LIBDEBUG_DEBUG, "%s %s\n", head, obuf);
|
||||||
|
}
|
||||||
|
free(obuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mi_shexprint(char *dest, unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
char *p = dest;
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
p += sprintf(p, "%02x ", *buf);
|
||||||
|
buf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
p--;
|
||||||
|
*p = 0;
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
/* $Id: fsm.c,v 2.0 2004/06/29 14:35:31 kkeil Exp $
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define FSM_TIMER_DEBUG 0
|
||||||
|
|
||||||
|
void
|
||||||
|
FsmNew(struct Fsm *fsm,
|
||||||
|
struct FsmNode *fnlist, int fncount)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fsm->jumpmatrix = (FSMFNPTR *)
|
||||||
|
malloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
|
||||||
|
if (!fsm->jumpmatrix)
|
||||||
|
return;
|
||||||
|
memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
|
||||||
|
for (i = 0; i < fncount; i++)
|
||||||
|
if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
|
||||||
|
eprint("FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
|
||||||
|
i,(long)fnlist[i].state,(long)fsm->state_count,
|
||||||
|
(long)fnlist[i].event,(long)fsm->event_count);
|
||||||
|
} else
|
||||||
|
fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
|
||||||
|
fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FsmFree(struct Fsm *fsm)
|
||||||
|
{
|
||||||
|
free(fsm->jumpmatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
FsmEvent(struct FsmInst *fi, int event, void *arg)
|
||||||
|
{
|
||||||
|
FSMFNPTR r;
|
||||||
|
|
||||||
|
if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) {
|
||||||
|
eprint("FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
|
||||||
|
(long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
|
||||||
|
if (r) {
|
||||||
|
if (fi->debug)
|
||||||
|
fi->printdebug(fi, "State %s Event %s",
|
||||||
|
fi->fsm->strState[fi->state],
|
||||||
|
fi->fsm->strEvent[event]);
|
||||||
|
r(fi, event, arg);
|
||||||
|
return (0);
|
||||||
|
} else {
|
||||||
|
if (fi->debug)
|
||||||
|
fi->printdebug(fi, "State %s Event %s no action",
|
||||||
|
fi->fsm->strState[fi->state],
|
||||||
|
fi->fsm->strEvent[event]);
|
||||||
|
return (!0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FsmChangeState(struct FsmInst *fi, int newstate)
|
||||||
|
{
|
||||||
|
if (fi->debug)
|
||||||
|
fi->printdebug(fi, "ChangeState %s -> %s",
|
||||||
|
fi->fsm->strState[fi->state], fi->fsm->strState[newstate]);
|
||||||
|
fi->state = newstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FsmExpireTimer(void *arg)
|
||||||
|
{
|
||||||
|
struct FsmTimer *ft = arg;
|
||||||
|
#if FSM_TIMER_DEBUG
|
||||||
|
if (ft->fi->debug)
|
||||||
|
ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
|
||||||
|
#endif
|
||||||
|
FsmEvent(ft->fi, ft->event, ft->arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
|
||||||
|
{
|
||||||
|
ft->fi = fi;
|
||||||
|
#if FSM_TIMER_DEBUG
|
||||||
|
if (ft->fi->debug)
|
||||||
|
ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
|
||||||
|
#endif
|
||||||
|
init_timer(&ft->tl, ft->fi->tb, ft, FsmExpireTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FsmDelTimer(struct FsmTimer *ft, int where)
|
||||||
|
{
|
||||||
|
#if FSM_TIMER_DEBUG
|
||||||
|
if (ft->fi->debug)
|
||||||
|
ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
|
||||||
|
#endif
|
||||||
|
del_timer(&ft->tl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
FsmAddTimer(struct FsmTimer *ft,
|
||||||
|
int millisec, int event, void *arg, int where)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if FSM_TIMER_DEBUG
|
||||||
|
if (ft->fi->debug)
|
||||||
|
ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
|
||||||
|
(long) ft, millisec, where);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (timer_pending(&ft->tl)) {
|
||||||
|
eprint("FsmAddTimer: timer already active!\n");
|
||||||
|
ft->fi->printdebug(ft->fi, "FsmAddTimer already active!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ft->event = event;
|
||||||
|
ft->arg = arg;
|
||||||
|
add_timer(&ft->tl, millisec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FsmRestartTimer(struct FsmTimer *ft,
|
||||||
|
int millisec, int event, void *arg, int where)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if FSM_TIMER_DEBUG
|
||||||
|
if (ft->fi->debug)
|
||||||
|
ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
|
||||||
|
(long) ft, millisec, where);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (timer_pending(&ft->tl))
|
||||||
|
del_timer(&ft->tl);
|
||||||
|
ft->event = event;
|
||||||
|
ft->arg = arg;
|
||||||
|
add_timer(&ft->tl, millisec);
|
||||||
|
}
|
|
@ -0,0 +1,457 @@
|
||||||
|
/* mbuffer.c
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
* Copyright 2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <mISDN/mbuffer.h>
|
||||||
|
#include "helper.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static struct mqueue free_queue_l2, free_queue_l3;
|
||||||
|
static int Max_Cache;
|
||||||
|
#define MIN_CACHE 4
|
||||||
|
|
||||||
|
#define MB_TYP_L2 2
|
||||||
|
#define MB_TYP_L3 3
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
#include <mISDN/q931.h>
|
||||||
|
|
||||||
|
static struct Aqueue {
|
||||||
|
struct lhead Alist;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
int len;
|
||||||
|
} AllocQueue;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
Aqueue_init(struct Aqueue *q)
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&q->lock, NULL);
|
||||||
|
q->len = 0;
|
||||||
|
q->Alist.prev = &q->Alist;
|
||||||
|
q->Alist.next = &q->Alist;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int Amqueue_len(struct Aqueue *q)
|
||||||
|
{
|
||||||
|
return q->len ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_add(struct lhead *new, struct lhead *prev, struct lhead *next)
|
||||||
|
{
|
||||||
|
next->prev = new;
|
||||||
|
new->next = next;
|
||||||
|
new->prev = prev;
|
||||||
|
prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_del(struct lhead * prev, struct lhead * next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Aqueue_head(struct Aqueue *q, struct mbuffer *newm)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
q->len++;
|
||||||
|
__list_add(&newm->Alist, &q->Alist, q->Alist.next);
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void Aqueue_tail(struct Aqueue *q, struct mbuffer *newm)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
q->len++;
|
||||||
|
__list_add(&newm->Alist, q->Alist.prev, &q->Alist);
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct mbuffer *Adequeue(struct Aqueue *q)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
struct lhead *le;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
if (q->len) {
|
||||||
|
le = q->Alist.next;
|
||||||
|
__list_del(le->prev, le->next);
|
||||||
|
q->len--;
|
||||||
|
m = container_of(le, struct mbuffer, Alist);
|
||||||
|
} else
|
||||||
|
m = NULL;
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
static void Aqueue_remove(struct Aqueue *q, struct mbuffer *mb)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&q->lock);
|
||||||
|
__list_del(mb->Alist.prev, mb->Alist.next);
|
||||||
|
q->len--;
|
||||||
|
pthread_mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
init_mbuffer(int max_cache)
|
||||||
|
{
|
||||||
|
mqueue_init(&free_queue_l2);
|
||||||
|
mqueue_init(&free_queue_l3);
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
Aqueue_init(&AllocQueue);
|
||||||
|
#endif
|
||||||
|
if (max_cache < MIN_CACHE)
|
||||||
|
max_cache = MIN_CACHE;
|
||||||
|
Max_Cache = max_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
__mqueue_purge(struct mqueue *q) {
|
||||||
|
struct mbuffer *mb;
|
||||||
|
|
||||||
|
while ((mb = mdequeue(q))!=NULL) {
|
||||||
|
if (mb->head)
|
||||||
|
free(mb->head);
|
||||||
|
if (mb->chead)
|
||||||
|
free(mb->chead);
|
||||||
|
free(mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MEMLEAK_DEBUG
|
||||||
|
|
||||||
|
static struct mbuffer *
|
||||||
|
_new_mbuffer(int typ, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
m = __mi_calloc(1, sizeof(struct mbuffer), file, lineno, func);
|
||||||
|
if (!m)
|
||||||
|
goto err;
|
||||||
|
switch(typ) {
|
||||||
|
case MB_TYP_L3:
|
||||||
|
m->chead = malloc(MBUFFER_DATA_SIZE);
|
||||||
|
if (!m->chead) {
|
||||||
|
free(m);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
m->cend = m->chead + MBUFFER_DATA_SIZE;
|
||||||
|
m->ctail = m->chead;
|
||||||
|
case MB_TYP_L2:
|
||||||
|
m->head = malloc(MBUFFER_DATA_SIZE);
|
||||||
|
if (!m->head) {
|
||||||
|
if (m->chead)
|
||||||
|
free(m->chead);
|
||||||
|
free(m);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
m->end = m->head + MBUFFER_DATA_SIZE;
|
||||||
|
m->data = m->tail = m->head;
|
||||||
|
m->h = (struct mISDNhead *) m->head;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(m);
|
||||||
|
err:
|
||||||
|
eprint("%s: no mem for mbuffer\n", __FUNCTION__);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mbuffer *
|
||||||
|
_alloc_mbuffer(int typ, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
switch(typ) {
|
||||||
|
case MB_TYP_L3:
|
||||||
|
m = mdequeue(&free_queue_l3);
|
||||||
|
break;
|
||||||
|
case MB_TYP_L2:
|
||||||
|
m = mdequeue(&free_queue_l2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
eprint("%s: wrong type %d\n", __func__, typ);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!m)
|
||||||
|
m = _new_mbuffer(typ, file, lineno, func);
|
||||||
|
else
|
||||||
|
__mi_reuse(m, file, lineno, func);
|
||||||
|
strncpy(m->d_fn, file, 79);
|
||||||
|
m->d_ln = lineno;
|
||||||
|
Aqueue_tail(&AllocQueue, m);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mbuffer *
|
||||||
|
__alloc_mbuffer(const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
return _alloc_mbuffer(MB_TYP_L2, file, lineno, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
__free_mbuffer(struct mbuffer *m, const char *file, int lineno, const char *func) {
|
||||||
|
if (!m)
|
||||||
|
return;
|
||||||
|
if (m->refcnt) {
|
||||||
|
m->refcnt--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Aqueue_remove(&AllocQueue, m);
|
||||||
|
strncpy(m->d_fn, file, 79);
|
||||||
|
m->d_ln = -lineno;
|
||||||
|
if (m->list) {
|
||||||
|
if (m->list == &free_queue_l3)
|
||||||
|
dprint(DBGM_L3BUFFER, "%s l3 buffer %p already freed: %lx\n", __FUNCTION__, m, (unsigned long)__builtin_return_address(0));
|
||||||
|
else if (m->list == &free_queue_l2)
|
||||||
|
dprint(DBGM_L3BUFFER, "%s l2 buffer %p already freed: %lx\n", __FUNCTION__, m, (unsigned long)__builtin_return_address(0));
|
||||||
|
else
|
||||||
|
dprint(DBGM_L3BUFFER, "%s buffer %p still in list %p : %lx\n", __FUNCTION__, m, m->list, (unsigned long)__builtin_return_address(0));
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
dprint(DBGM_L3BUFFER, "%s buffer %p freed: %lx\n", __FUNCTION__, m, (unsigned long)__builtin_return_address(0));
|
||||||
|
if (m->chead) {
|
||||||
|
if (free_queue_l3.len > Max_Cache) {
|
||||||
|
free(m->chead);
|
||||||
|
free(m->head);
|
||||||
|
__mi_free(m, file, lineno, func);
|
||||||
|
} else {
|
||||||
|
memset(&m->l3, 0, sizeof(m->l3));
|
||||||
|
memset(&m->l3h, 0, sizeof(m->l3h));
|
||||||
|
m->data = m->tail = m->head;
|
||||||
|
m->len = 0;
|
||||||
|
m->ctail = m->chead;
|
||||||
|
__mi_reuse(m, file, lineno, "IN_FREE_QUEUE");
|
||||||
|
mqueue_head(&free_queue_l3, m);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (free_queue_l2.len > Max_Cache) {
|
||||||
|
free(m->head);
|
||||||
|
__mi_free(m, file, lineno, func);
|
||||||
|
} else {
|
||||||
|
memset(&m->l3, 0, sizeof(m->l3));
|
||||||
|
memset(&m->l3h, 0, sizeof(m->l3h));
|
||||||
|
m->data = m->tail = m->head;
|
||||||
|
m->len = 0;
|
||||||
|
__mi_reuse(m, file, lineno, "IN_FREE_QUEUE");
|
||||||
|
mqueue_head(&free_queue_l2, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct l3_msg *
|
||||||
|
__alloc_l3_msg(const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
m = _alloc_mbuffer(MB_TYP_L3, file, lineno, func);
|
||||||
|
if (m)
|
||||||
|
return &m->l3;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__free_l3_msg(struct l3_msg *l3m, const char *file, int lineno, const char *func)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
if (!l3m)
|
||||||
|
return;
|
||||||
|
m = container_of(l3m, struct mbuffer, l3);
|
||||||
|
__free_mbuffer(m, file, lineno, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup_mbuffer(void)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
int ql;
|
||||||
|
|
||||||
|
__mqueue_purge(&free_queue_l2);
|
||||||
|
__mqueue_purge(&free_queue_l3);
|
||||||
|
ql = Amqueue_len(&AllocQueue);
|
||||||
|
iprint("AllocQueue has %d lost mbuffer\n", ql);
|
||||||
|
if (ql) {
|
||||||
|
m = Adequeue(&AllocQueue);
|
||||||
|
while (m) {
|
||||||
|
wprint("Lost mbuffer allocated %s:%d typ=%s len=%d\n",
|
||||||
|
m->d_fn, m->d_ln, m->chead ? "L3" : "L2", m->len);
|
||||||
|
wprint(" H: prim=%s id=%d L3: prim=%s pid=%d\n",
|
||||||
|
_mi_msg_type2str(m->h->prim), m->h->id, _mi_msg_type2str(m->l3.type), m->l3.pid);
|
||||||
|
free_mbuffer(m);
|
||||||
|
m = Adequeue(&AllocQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static struct mbuffer *
|
||||||
|
_new_mbuffer(int typ)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
m = calloc(1, sizeof(struct mbuffer));
|
||||||
|
if (!m)
|
||||||
|
goto err;
|
||||||
|
switch(typ) {
|
||||||
|
case MB_TYP_L3:
|
||||||
|
m->chead = malloc(MBUFFER_DATA_SIZE);
|
||||||
|
if (!m->chead) {
|
||||||
|
free(m);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
m->cend = m->chead + MBUFFER_DATA_SIZE;
|
||||||
|
m->ctail = m->chead;
|
||||||
|
/* FALLTHRU */
|
||||||
|
case MB_TYP_L2:
|
||||||
|
m->head = malloc(MBUFFER_DATA_SIZE);
|
||||||
|
if (!m->head) {
|
||||||
|
if (m->chead)
|
||||||
|
free(m->chead);
|
||||||
|
free(m);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
m->end = m->head + MBUFFER_DATA_SIZE;
|
||||||
|
m->data = m->tail = m->head;
|
||||||
|
m->h = (struct mISDNhead *) m->head;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(m);
|
||||||
|
err:
|
||||||
|
eprint("%s: no mem for mbuffer\n", __FUNCTION__);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mbuffer *
|
||||||
|
_alloc_mbuffer(int typ)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
switch(typ) {
|
||||||
|
case MB_TYP_L3:
|
||||||
|
m = mdequeue(&free_queue_l3);
|
||||||
|
break;
|
||||||
|
case MB_TYP_L2:
|
||||||
|
m = mdequeue(&free_queue_l2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
eprint("%s: wrong type %d\n", __func__, typ);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!m)
|
||||||
|
m = _new_mbuffer(typ);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mbuffer *
|
||||||
|
alloc_mbuffer(void)
|
||||||
|
{
|
||||||
|
return _alloc_mbuffer(MB_TYP_L2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
free_mbuffer(struct mbuffer *m) {
|
||||||
|
if (!m)
|
||||||
|
return;
|
||||||
|
if (m->refcnt) {
|
||||||
|
m->refcnt--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m->list) {
|
||||||
|
if (m->list == &free_queue_l3)
|
||||||
|
dprint(DBGM_L3BUFFER, "%s l3 buffer %p already freed: %lx\n", __FUNCTION__, m, (unsigned long)__builtin_return_address(0));
|
||||||
|
else if (m->list == &free_queue_l2)
|
||||||
|
dprint(DBGM_L3BUFFER, "%s l2 buffer %p already freed: %lx\n", __FUNCTION__, m, (unsigned long)__builtin_return_address(0));
|
||||||
|
else
|
||||||
|
dprint(DBGM_L3BUFFER, "%s buffer %p still in list %p : %lx\n", __FUNCTION__, m, m->list, (unsigned long)__builtin_return_address(0));
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
dprint(DBGM_L3BUFFER, "%s buffer %p freed: %lx\n", __FUNCTION__, m, (unsigned long)__builtin_return_address(0));
|
||||||
|
if (m->chead) {
|
||||||
|
if (free_queue_l3.len > Max_Cache) {
|
||||||
|
free(m->chead);
|
||||||
|
free(m->head);
|
||||||
|
free(m);
|
||||||
|
} else {
|
||||||
|
memset(&m->l3, 0, sizeof(m->l3));
|
||||||
|
memset(&m->l3h, 0, sizeof(m->l3h));
|
||||||
|
m->data = m->tail = m->head;
|
||||||
|
m->len = 0;
|
||||||
|
m->ctail = m->chead;
|
||||||
|
mqueue_head(&free_queue_l3, m);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (free_queue_l2.len > Max_Cache) {
|
||||||
|
free(m->head);
|
||||||
|
free(m);
|
||||||
|
} else {
|
||||||
|
memset(&m->l3, 0, sizeof(m->l3));
|
||||||
|
memset(&m->l3h, 0, sizeof(m->l3h));
|
||||||
|
m->data = m->tail = m->head;
|
||||||
|
m->len = 0;
|
||||||
|
mqueue_head(&free_queue_l2, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct l3_msg *
|
||||||
|
alloc_l3_msg(void)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
m = _alloc_mbuffer(MB_TYP_L3);
|
||||||
|
if (m)
|
||||||
|
return &m->l3;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_l3_msg(struct l3_msg *l3m)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
if (!l3m)
|
||||||
|
return;
|
||||||
|
m = container_of(l3m, struct mbuffer, l3);
|
||||||
|
free_mbuffer(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup_mbuffer(void)
|
||||||
|
{
|
||||||
|
__mqueue_purge(&free_queue_l2);
|
||||||
|
__mqueue_purge(&free_queue_l3);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
l3_msg_increment_refcnt(struct l3_msg *l3m)
|
||||||
|
{
|
||||||
|
struct mbuffer *m;
|
||||||
|
|
||||||
|
m = container_of(l3m, struct mbuffer, l3);
|
||||||
|
m->refcnt++;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
/* mtimer.c
|
||||||
|
*
|
||||||
|
* Author Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "mtimer.h"
|
||||||
|
#include "layer3.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
//#define DEBUG_TIMERS
|
||||||
|
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
void debug_list(struct timer_base *tb)
|
||||||
|
{
|
||||||
|
struct mtimer *mt;
|
||||||
|
|
||||||
|
printf("list all timers of tb=%p:\n", tb);
|
||||||
|
list_for_each_entry(mt, &tb->pending_timer, list) {
|
||||||
|
printf(" - timer %p\n", mt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
init_timer(struct mtimer *mt, struct timer_base *tb, void *data, mtimer_func_t *f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("init timer %p\n", mt);
|
||||||
|
#endif
|
||||||
|
mt->tb = tb;
|
||||||
|
mt->id = 0;
|
||||||
|
mt->data = data;
|
||||||
|
mt->function = f;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nextid = 1;
|
||||||
|
|
||||||
|
int
|
||||||
|
add_timer(struct mtimer *mt, int tout)
|
||||||
|
{
|
||||||
|
int ret, para;
|
||||||
|
struct mtimer *check;
|
||||||
|
|
||||||
|
/* hack to be sure that timer will fire even when no or negative time was given */
|
||||||
|
if (tout < 1)
|
||||||
|
tout = 1;
|
||||||
|
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("add timer %p (timeout=%d ms)\n", mt, tout);
|
||||||
|
debug_list(mt->tb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mt->timeout = tout;
|
||||||
|
para = tout;
|
||||||
|
if (mt->tb->tdev) {
|
||||||
|
ret = ioctl(mt->tb->tdev, IMADDTIMER, (long)¶);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
mt->id = para;
|
||||||
|
} else {
|
||||||
|
static struct timespec tv;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tv);
|
||||||
|
mt->expires = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
|
||||||
|
mt->expires += (double)tout / 1000.0;
|
||||||
|
ret = 0;
|
||||||
|
mt->id = nextid++;
|
||||||
|
}
|
||||||
|
list_for_each_entry(check, &mt->tb->pending_timer, list) {
|
||||||
|
if (check == mt) {
|
||||||
|
eprint("%s: timer already in list!\n", __func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_add_tail(&mt->list, &mt->tb->pending_timer);
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("add timer done\n");
|
||||||
|
debug_list(mt->tb);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
del_timer(struct mtimer *mt)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("del timer %p id=%d\n", mt, mt->id);
|
||||||
|
debug_list(mt->tb);
|
||||||
|
#endif
|
||||||
|
if (mt->id) {
|
||||||
|
list_del(&mt->list);
|
||||||
|
ret = ioctl(mt->tb->tdev, IMDELTIMER, (long)&mt->id);
|
||||||
|
mt->id = 0;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("del timer done\n");
|
||||||
|
debug_list(mt->tb);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
timer_pending(struct mtimer *mt)
|
||||||
|
{
|
||||||
|
return mt->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int expire_timer(struct timer_base *tb, int id)
|
||||||
|
{
|
||||||
|
struct mtimer *mt;
|
||||||
|
double now = 0.0;
|
||||||
|
int work = 0;
|
||||||
|
|
||||||
|
/* if id is < 0, then check for expired timer */
|
||||||
|
if (id < 0) {
|
||||||
|
static struct timespec tv;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tv);
|
||||||
|
now = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
again:
|
||||||
|
list_for_each_entry(mt, &tb->pending_timer, list) {
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
// printf("check timer in list %p\n", mt);
|
||||||
|
#endif
|
||||||
|
if (id >= 0 && mt->id == id) {
|
||||||
|
work |= 1;
|
||||||
|
list_del(&mt->list);
|
||||||
|
mt->id = 0;
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("calling expire function\n");
|
||||||
|
debug_list(tb);
|
||||||
|
#endif
|
||||||
|
mt->function(mt->data);
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("expire functiion finished\n");
|
||||||
|
debug_list(tb);
|
||||||
|
#endif
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
if (id < 0 && now >= mt->expires) {
|
||||||
|
work |= 1;
|
||||||
|
list_del(&mt->list);
|
||||||
|
mt->expires = 0.0;
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("calling expire function\n");
|
||||||
|
debug_list(tb);
|
||||||
|
#endif
|
||||||
|
mt->function(mt->data);
|
||||||
|
#ifdef DEBUG_TIMERS
|
||||||
|
printf("expire functiion finished\n");
|
||||||
|
debug_list(tb);
|
||||||
|
#endif
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return work;
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Three Party (3PTY) Supplementary Services ETS 300 188-2
|
||||||
|
*
|
||||||
|
* ECT Facility ie encode/decode
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
* Copyright 2012 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include "3pty.h"
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the Begin3PTY facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacBegin3PTY(__u8 * Dest, const struct asn1_parm *pc, const void *unused)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *SeqStart;
|
||||||
|
|
||||||
|
switch (pc->comp) {
|
||||||
|
case CompInvoke:
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_Begin3PTY);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
case CompReturnResult:
|
||||||
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
||||||
|
|
||||||
|
SeqStart = p;
|
||||||
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &SeqStart[2];
|
||||||
|
|
||||||
|
p += encodeOperationValue(p, Fac_Begin3PTY);
|
||||||
|
|
||||||
|
/* sequence Length */
|
||||||
|
SeqStart[1] = p - &SeqStart[2];
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length = -1;
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacEctLoopTest() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the End3PTY facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacEnd3PTY(__u8 * Dest, const struct asn1_parm *pc, const void *unused)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *SeqStart;
|
||||||
|
|
||||||
|
switch (pc->comp) {
|
||||||
|
case CompInvoke:
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_End3PTY);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
case CompReturnResult:
|
||||||
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
||||||
|
|
||||||
|
SeqStart = p;
|
||||||
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &SeqStart[2];
|
||||||
|
|
||||||
|
p += encodeOperationValue(p, Fac_End3PTY);
|
||||||
|
|
||||||
|
/* sequence Length */
|
||||||
|
SeqStart[1] = p - &SeqStart[2];
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length = -1;
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacEctLoopTest() */
|
|
@ -0,0 +1,624 @@
|
||||||
|
/* $Id$
|
||||||
|
*
|
||||||
|
* Addressing-Data-Elements ETS 300 196-1 D.3
|
||||||
|
*
|
||||||
|
* Addressing-Data-Elements encode/decode
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the NumberDigits PartyNumber argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartyNumber Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseNumberDigits_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartyNumber *PartyNumber)
|
||||||
|
{
|
||||||
|
struct asn1ParseString Number;
|
||||||
|
int LengthConsumed;
|
||||||
|
|
||||||
|
Number.buf = (char *)PartyNumber->Number;
|
||||||
|
Number.maxSize = sizeof(PartyNumber->Number);
|
||||||
|
Number.length = 0;
|
||||||
|
LengthConsumed = ParseNumericString(pc, p, end, &Number);
|
||||||
|
PartyNumber->LengthOfNumber = Number.length;
|
||||||
|
return LengthConsumed;
|
||||||
|
} /* end ParseNumberDigits_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the NSAP PartyNumber argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartyNumber Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseNSAPPartyNumber(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartyNumber *PartyNumber)
|
||||||
|
{
|
||||||
|
struct asn1ParseString Number;
|
||||||
|
int LengthConsumed;
|
||||||
|
|
||||||
|
Number.buf = (char *)PartyNumber->Number;
|
||||||
|
Number.maxSize = sizeof(PartyNumber->Number);
|
||||||
|
Number.length = 0;
|
||||||
|
LengthConsumed = ParseOctetString(pc, p, end, &Number);
|
||||||
|
PartyNumber->LengthOfNumber = Number.length;
|
||||||
|
return LengthConsumed;
|
||||||
|
} /* end ParseNSAPPartyNumber() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Encode the public or private network PartyNumber type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param Number
|
||||||
|
* \param LengthOfNumber
|
||||||
|
* \param TypeOfNumber
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
static int encodeNetworkPartyNumber(__u8 * Dest, const __s8 * Number, __u8 LengthOfNumber, __u8 TypeOfNumber)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
Dest[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &Dest[2];
|
||||||
|
|
||||||
|
p += encodeEnum(p, ASN1_TAG_ENUM, TypeOfNumber);
|
||||||
|
p += encodeNumericString(p, ASN1_TAG_NUMERIC_STRING, Number, LengthOfNumber);
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
Dest[1] = p - &Dest[2];
|
||||||
|
|
||||||
|
return p - Dest;
|
||||||
|
} /* end encodeNetworkPartyNumber() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the public or private network PartyNumber argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartyNumber Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseNetworkPartyNumber(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartyNumber *PartyNumber)
|
||||||
|
{
|
||||||
|
unsigned int TypeOfNumber;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &TypeOfNumber);
|
||||||
|
PartyNumber->TypeOfNumber = TypeOfNumber;
|
||||||
|
XSEQUENCE_1(ParseNumberDigits_Full, ASN1_TAG_NUMERIC_STRING, ASN1_NOT_TAGGED, PartyNumber);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseNetworkPartyNumber() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the PartyNumber type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param PartyNumber Number information to encode.
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
int encodePartyNumber_Full(__u8 * Dest, const struct FacPartyNumber *PartyNumber)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
|
||||||
|
switch (PartyNumber->Type) {
|
||||||
|
case 0: /* Unknown PartyNumber */
|
||||||
|
Length =
|
||||||
|
encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 0, (const __s8 *)PartyNumber->Number,
|
||||||
|
PartyNumber->LengthOfNumber);
|
||||||
|
break;
|
||||||
|
case 1: /* Public PartyNumber */
|
||||||
|
Length =
|
||||||
|
encodeNetworkPartyNumber(Dest, (const __s8 *)PartyNumber->Number, PartyNumber->LengthOfNumber,
|
||||||
|
PartyNumber->TypeOfNumber);
|
||||||
|
Dest[0] &= ASN1_TAG_CONSTRUCTED;
|
||||||
|
Dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 1;
|
||||||
|
break;
|
||||||
|
case 2: /* NSAP encoded PartyNumber */
|
||||||
|
Length =
|
||||||
|
encodeOctetString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 2, (const __s8 *)PartyNumber->Number,
|
||||||
|
PartyNumber->LengthOfNumber);
|
||||||
|
break;
|
||||||
|
case 3: /* Data PartyNumber (Not used) */
|
||||||
|
Length =
|
||||||
|
encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 3, (const __s8 *)PartyNumber->Number,
|
||||||
|
PartyNumber->LengthOfNumber);
|
||||||
|
break;
|
||||||
|
case 4: /* Telex PartyNumber (Not used) */
|
||||||
|
Length =
|
||||||
|
encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 4, (const __s8 *)PartyNumber->Number,
|
||||||
|
PartyNumber->LengthOfNumber);
|
||||||
|
break;
|
||||||
|
case 5: /* Private PartyNumber */
|
||||||
|
Length =
|
||||||
|
encodeNetworkPartyNumber(Dest, (const __s8 *)PartyNumber->Number, PartyNumber->LengthOfNumber,
|
||||||
|
PartyNumber->TypeOfNumber);
|
||||||
|
Dest[0] &= ASN1_TAG_CONSTRUCTED;
|
||||||
|
Dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 5;
|
||||||
|
break;
|
||||||
|
case 8: /* National Standard PartyNumber (Not used) */
|
||||||
|
Length =
|
||||||
|
encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 8, (const __s8 *)PartyNumber->Number,
|
||||||
|
PartyNumber->LengthOfNumber);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length = 0;
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodePartyNumber_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the PartyNumber argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartyNumber Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParsePartyNumber_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartyNumber *PartyNumber)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
PartyNumber->Type = 0; /* Unknown PartyNumber */
|
||||||
|
XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 0, PartyNumber);
|
||||||
|
PartyNumber->Type = 1; /* Public PartyNumber */
|
||||||
|
XCHOICE_1(ParseNetworkPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, PartyNumber);
|
||||||
|
PartyNumber->Type = 2; /* NSAP encoded PartyNumber */
|
||||||
|
XCHOICE_1(ParseNSAPPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC, 2, PartyNumber);
|
||||||
|
PartyNumber->Type = 3; /* Data PartyNumber (Not used) */
|
||||||
|
XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 3, PartyNumber);
|
||||||
|
PartyNumber->Type = 4; /* Telex PartyNumber (Not used) */
|
||||||
|
XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 4, PartyNumber);
|
||||||
|
PartyNumber->Type = 5; /* Private PartyNumber */
|
||||||
|
XCHOICE_1(ParseNetworkPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 5, PartyNumber);
|
||||||
|
PartyNumber->Type = 8; /* National Standard PartyNumber (Not used) */
|
||||||
|
XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 8, PartyNumber);
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
} /* end ParsePartyNumber_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the User information string PartySubaddress argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartySubaddress Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseUserSubaddressInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartySubaddress *PartySubaddress)
|
||||||
|
{
|
||||||
|
struct asn1ParseString Subaddress;
|
||||||
|
int LengthConsumed;
|
||||||
|
|
||||||
|
Subaddress.buf = (char *)PartySubaddress->u.UserSpecified.Information;
|
||||||
|
Subaddress.maxSize = sizeof(PartySubaddress->u.UserSpecified.Information);
|
||||||
|
Subaddress.length = 0;
|
||||||
|
LengthConsumed = ParseOctetString(pc, p, end, &Subaddress);
|
||||||
|
PartySubaddress->Length = Subaddress.length;
|
||||||
|
return LengthConsumed;
|
||||||
|
} /* end ParseUserSubaddressInfo() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the User PartySubaddress argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartySubaddress Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseUserSubaddress(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartySubaddress *PartySubaddress)
|
||||||
|
{
|
||||||
|
int OddCount;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
PartySubaddress->Type = 0; /* UserSpecified */
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseUserSubaddressInfo, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, PartySubaddress);
|
||||||
|
if (p < end) {
|
||||||
|
XSEQUENCE_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &OddCount);
|
||||||
|
PartySubaddress->u.UserSpecified.OddCount = OddCount;
|
||||||
|
PartySubaddress->u.UserSpecified.OddCountPresent = 1;
|
||||||
|
} else {
|
||||||
|
PartySubaddress->u.UserSpecified.OddCount = 0;
|
||||||
|
PartySubaddress->u.UserSpecified.OddCountPresent = 0;
|
||||||
|
}
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseUserSubaddress() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the NSAP PartySubaddress argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartySubaddress Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseNSAPSubaddress_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartySubaddress *PartySubaddress)
|
||||||
|
{
|
||||||
|
struct asn1ParseString Subaddress;
|
||||||
|
int LengthConsumed;
|
||||||
|
|
||||||
|
PartySubaddress->Type = 1; /* NSAP */
|
||||||
|
|
||||||
|
Subaddress.buf = (char *)PartySubaddress->u.Nsap;
|
||||||
|
Subaddress.maxSize = sizeof(PartySubaddress->u.Nsap);
|
||||||
|
Subaddress.length = 0;
|
||||||
|
LengthConsumed = ParseOctetString(pc, p, end, &Subaddress);
|
||||||
|
PartySubaddress->Length = Subaddress.length;
|
||||||
|
return LengthConsumed;
|
||||||
|
} /* end ParseNSAPSubaddress_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the PartySubaddress type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param PartySubaddress Subaddress information to encode.
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
int encodePartySubaddress_Full(__u8 * Dest, const struct FacPartySubaddress *PartySubaddress)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
int Length;
|
||||||
|
|
||||||
|
switch (PartySubaddress->Type) {
|
||||||
|
case 0: /* UserSpecified */
|
||||||
|
Dest[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &Dest[2];
|
||||||
|
|
||||||
|
p += encodeOctetString(p, ASN1_TAG_OCTET_STRING, (const __s8 *)PartySubaddress->u.UserSpecified.Information,
|
||||||
|
PartySubaddress->Length);
|
||||||
|
if (PartySubaddress->u.UserSpecified.OddCountPresent) {
|
||||||
|
p += encodeBoolean(p, ASN1_TAG_BOOLEAN, PartySubaddress->u.UserSpecified.OddCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
Dest[1] = p - &Dest[2];
|
||||||
|
|
||||||
|
Length = p - Dest;
|
||||||
|
break;
|
||||||
|
case 1: /* NSAP */
|
||||||
|
Length =
|
||||||
|
encodeOctetString(Dest, ASN1_TAG_OCTET_STRING, (const __s8 *)PartySubaddress->u.Nsap, PartySubaddress->Length);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length = 0;
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodePartySubaddress_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the PartySubaddress argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param PartySubaddress Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParsePartySubaddress_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartySubaddress *PartySubaddress)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseUserSubaddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, PartySubaddress);
|
||||||
|
XCHOICE_1(ParseNSAPSubaddress_Full, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, PartySubaddress);
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
} /* end ParsePartySubaddress_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the Address type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param Address Address information to encode.
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
int encodeAddress_Full(__u8 * Dest, const struct FacAddress *Address)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
Dest[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &Dest[2];
|
||||||
|
|
||||||
|
p += encodePartyNumber_Full(p, &Address->Party);
|
||||||
|
if (Address->Subaddress.Length) {
|
||||||
|
p += encodePartySubaddress_Full(p, &Address->Subaddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
Dest[1] = p - &Dest[2];
|
||||||
|
|
||||||
|
return p - Dest;
|
||||||
|
} /* end encodeAddress_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the Address argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param Address Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseAddress_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAddress *Address)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParsePartyNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &Address->Party);
|
||||||
|
if (p < end) {
|
||||||
|
/* The optional subaddress must be present since there is something left. */
|
||||||
|
XSEQUENCE_1(ParsePartySubaddress_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &Address->Subaddress);
|
||||||
|
} else {
|
||||||
|
Address->Subaddress.Length = 0; /* Subaddress not present */
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseAddress_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the PresentedNumberUnscreened type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param Presented Number information to encode.
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
int encodePresentedNumberUnscreened_Full(__u8 * Dest, const struct FacPresentedNumberUnscreened *Presented)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *TagStart;
|
||||||
|
|
||||||
|
p = Dest;
|
||||||
|
switch (Presented->Type) {
|
||||||
|
case 0: /* presentationAllowedNumber */
|
||||||
|
TagStart = p;
|
||||||
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 0;
|
||||||
|
p = &TagStart[2];
|
||||||
|
|
||||||
|
p += encodePartyNumber_Full(p, &Presented->Unscreened);
|
||||||
|
|
||||||
|
/* tag Length */
|
||||||
|
TagStart[1] = p - &TagStart[2];
|
||||||
|
break;
|
||||||
|
case 1: /* presentationRestricted */
|
||||||
|
p += encodeNull(p, ASN1_TAG_CONTEXT_SPECIFIC | 1);
|
||||||
|
break;
|
||||||
|
case 2: /* numberNotAvailableDueToInterworking */
|
||||||
|
p += encodeNull(p, ASN1_TAG_CONTEXT_SPECIFIC | 2);
|
||||||
|
break;
|
||||||
|
case 3: /* presentationRestrictedNumber */
|
||||||
|
TagStart = p;
|
||||||
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3;
|
||||||
|
p = &TagStart[2];
|
||||||
|
|
||||||
|
p += encodePartyNumber_Full(p, &Presented->Unscreened);
|
||||||
|
|
||||||
|
/* tag Length */
|
||||||
|
TagStart[1] = p - &TagStart[2];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return p - Dest;
|
||||||
|
} /* end encodePresentedNumberUnscreened_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the PresentedNumberUnscreened argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param Presented Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParsePresentedNumberUnscreened_Full(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacPresentedNumberUnscreened *Presented)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
Presented->Type = 0;
|
||||||
|
XCHOICE_1(ParsePartyNumber_Full, ASN1_TAG_EXPLICIT | ASN1_TAG_CONTEXT_SPECIFIC, 0, &Presented->Unscreened);
|
||||||
|
Presented->Type = 1;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1);
|
||||||
|
Presented->Type = 2;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 2);
|
||||||
|
Presented->Type = 3;
|
||||||
|
XCHOICE_1(ParsePartyNumber_Full, ASN1_TAG_EXPLICIT | ASN1_TAG_CONTEXT_SPECIFIC, 3, &Presented->Unscreened);
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
} /* end ParsePresentedNumberUnscreened_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Encode the AddressScreened type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param Address Address information to encode.
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
static int encodeAddressScreened_Full(__u8 * Dest, const struct FacAddressScreened *Address)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
Dest[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &Dest[2];
|
||||||
|
|
||||||
|
p += encodePartyNumber_Full(p, &Address->Party);
|
||||||
|
p += encodeEnum(p, ASN1_TAG_ENUM, Address->ScreeningIndicator);
|
||||||
|
if (Address->Subaddress.Length) {
|
||||||
|
p += encodePartySubaddress_Full(p, &Address->Subaddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
Dest[1] = p - &Dest[2];
|
||||||
|
|
||||||
|
return p - Dest;
|
||||||
|
} /* end encodeAddressScreened_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Parse the AddressScreened argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param Address Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
static int ParseAddressScreened_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAddressScreened *Address)
|
||||||
|
{
|
||||||
|
unsigned int Value;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParsePartyNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &Address->Party);
|
||||||
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
||||||
|
Address->ScreeningIndicator = Value;
|
||||||
|
if (p < end) {
|
||||||
|
/* The optional subaddress must be present since there is something left. */
|
||||||
|
XSEQUENCE_1(ParsePartySubaddress_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &Address->Subaddress);
|
||||||
|
} else {
|
||||||
|
Address->Subaddress.Length = 0; /* Subaddress not present */
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseAddressScreened_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the PresentedAddressScreened type.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param Presented Address information to encode.
|
||||||
|
*
|
||||||
|
* \retval length
|
||||||
|
*/
|
||||||
|
int encodePresentedAddressScreened_Full(__u8 * Dest, const struct FacPresentedAddressScreened *Presented)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *TagStart;
|
||||||
|
|
||||||
|
p = Dest;
|
||||||
|
switch (Presented->Type) {
|
||||||
|
case 0: /* presentationAllowedAddress */
|
||||||
|
TagStart = p;
|
||||||
|
p += encodeAddressScreened_Full(p, &Presented->Address);
|
||||||
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 0;
|
||||||
|
break;
|
||||||
|
case 1: /* presentationRestricted */
|
||||||
|
p += encodeNull(p, ASN1_TAG_CONTEXT_SPECIFIC | 1);
|
||||||
|
break;
|
||||||
|
case 2: /* numberNotAvailableDueToInterworking */
|
||||||
|
p += encodeNull(p, ASN1_TAG_CONTEXT_SPECIFIC | 2);
|
||||||
|
break;
|
||||||
|
case 3: /* presentationRestrictedAddress */
|
||||||
|
TagStart = p;
|
||||||
|
p += encodeAddressScreened_Full(p, &Presented->Address);
|
||||||
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return p - Dest;
|
||||||
|
} /* end encodePresentedAddressScreened_Full() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the PresentedAddressScreened argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param Presented Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParsePresentedAddressScreened_Full(struct asn1_parm *pc, u_char * p, u_char * end,
|
||||||
|
struct FacPresentedAddressScreened *Presented)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
Presented->Type = 0;
|
||||||
|
XCHOICE_1(ParseAddressScreened_Full, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 0, &Presented->Address);
|
||||||
|
Presented->Type = 1;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1);
|
||||||
|
Presented->Type = 2;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 2);
|
||||||
|
Presented->Type = 3;
|
||||||
|
XCHOICE_1(ParseAddressScreened_Full, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 3, &Presented->Address);
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
} /* end ParsePresentedAddressScreened_Full() */
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
/* end asn1_address.c */
|
|
@ -0,0 +1,348 @@
|
||||||
|
/* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// AOC EN 300 182-1 V1.3.3
|
||||||
|
|
||||||
|
int ParseAOCDCurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
cur->chargeNotAvailable = 1;
|
||||||
|
cur->freeOfCharge = 0;
|
||||||
|
memset(cur->currency, 0, sizeof(cur->currency));
|
||||||
|
cur->currencyAmount = 0;
|
||||||
|
cur->multiplier = 0;
|
||||||
|
cur->typeOfChargingInfo = -1;
|
||||||
|
cur->billingId = -1;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
|
||||||
|
cur->chargeNotAvailable = 0;
|
||||||
|
XCHOICE_1(ParseAOCDCurrencyInfo, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, cur);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCDChargingUnit(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
chu->chargeNotAvailable = 1;
|
||||||
|
chu->freeOfCharge = 0;
|
||||||
|
chu->recordedUnits = 0;
|
||||||
|
chu->typeOfChargingInfo = -1;
|
||||||
|
chu->billingId = -1;
|
||||||
|
memset(chu->chargeNumber, 0, sizeof(chu->chargeNumber));
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
|
||||||
|
chu->chargeNotAvailable = 0;
|
||||||
|
XCHOICE_1(ParseAOCDChargingUnitInfo, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, chu);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCECurrency
|
||||||
|
|
||||||
|
int ParseAOCECurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
cur->chargeNotAvailable = 1;
|
||||||
|
cur->freeOfCharge = 0;
|
||||||
|
memset(cur->currency, 0, sizeof(cur->currency));
|
||||||
|
cur->currencyAmount = 0;
|
||||||
|
cur->multiplier = 0;
|
||||||
|
cur->typeOfChargingInfo = -1;
|
||||||
|
cur->billingId = -1;
|
||||||
|
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
|
||||||
|
cur->chargeNotAvailable = 0;
|
||||||
|
XCHOICE_1(ParseAOCECurrencyInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, cur);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCEChargingUnit
|
||||||
|
|
||||||
|
int ParseAOCEChargingUnit(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
chu->chargeNotAvailable = 1;
|
||||||
|
chu->freeOfCharge = 0;
|
||||||
|
chu->recordedUnits = 0;
|
||||||
|
chu->typeOfChargingInfo = -1;
|
||||||
|
chu->billingId = -1;
|
||||||
|
memset(chu->chargeNumber, 0, sizeof(chu->chargeNumber));
|
||||||
|
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
|
||||||
|
XCHOICE_1(ParseAOCEChargingUnitInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, chu);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCDCurrencyInfo
|
||||||
|
|
||||||
|
int ParseAOCDSpecificCurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseRecordedCurrency, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, cur);
|
||||||
|
XSEQUENCE_1(ParseTypeOfChargingInfo, ASN1_TAG_CONTEXT_SPECIFIC, 2, &cur->typeOfChargingInfo);
|
||||||
|
XSEQUENCE_OPT_1(ParseAOCDBillingId, ASN1_TAG_CONTEXT_SPECIFIC, 3, &cur->billingId);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCDCurrencyInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseAOCDSpecificCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, cur);
|
||||||
|
|
||||||
|
cur->freeOfCharge = 1;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1); // freeOfCharge
|
||||||
|
cur->freeOfCharge = 0;
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCDChargingUnitInfo
|
||||||
|
|
||||||
|
int ParseAOCDSpecificChargingUnits(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseRecordedUnitsList, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, &chu->recordedUnits);
|
||||||
|
XSEQUENCE_1(ParseTypeOfChargingInfo, ASN1_TAG_CONTEXT_SPECIFIC, 2, &chu->typeOfChargingInfo);
|
||||||
|
XSEQUENCE_OPT_1(ParseAOCDBillingId, ASN1_TAG_CONTEXT_SPECIFIC, 3, &chu->billingId);
|
||||||
|
|
||||||
|
// p_L3L4(pc, CC_CHARGE | INDICATION, &recordedUnits);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCDChargingUnitInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseAOCDSpecificChargingUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, chu);
|
||||||
|
|
||||||
|
chu->freeOfCharge = 1;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1); // freeOfCharge
|
||||||
|
chu->freeOfCharge = 0;
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordedCurrency
|
||||||
|
|
||||||
|
int ParseRecordedCurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseCurrency, ASN1_TAG_CONTEXT_SPECIFIC, 1, (char *)cur->currency);
|
||||||
|
XSEQUENCE_1(ParseAmount, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 2, cur);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordedUnitsList
|
||||||
|
|
||||||
|
int ParseRecordedUnitsList(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *recordedUnits)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
__u32 units;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
*recordedUnits = 0;
|
||||||
|
XSEQUENCE_1(ParseRecordedUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, recordedUnits);
|
||||||
|
for (i = 0; i < 31; i++) {
|
||||||
|
units = 0;
|
||||||
|
XSEQUENCE_OPT_1(ParseRecordedUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &units);
|
||||||
|
*recordedUnits += units;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeOfChargingInfo
|
||||||
|
|
||||||
|
int ParseTypeOfChargingInfo(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *typeOfChargingInfo)
|
||||||
|
{
|
||||||
|
return ParseEnum(pc, p, end, typeOfChargingInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordedUnits
|
||||||
|
|
||||||
|
int ParseRecordedUnitsChoice(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *recordedUnits)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseNumberOfUnits, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, recordedUnits);
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // not available
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseRecordedUnits(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *recordedUnits)
|
||||||
|
{
|
||||||
|
__u32 typeOfUnit;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseRecordedUnitsChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, recordedUnits);
|
||||||
|
XSEQUENCE_OPT_1(ParseTypeOfUnit, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &typeOfUnit);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCDBillingId
|
||||||
|
|
||||||
|
int ParseAOCDBillingId(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *billingId)
|
||||||
|
{
|
||||||
|
return ParseEnum(pc, p, end, billingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #if 0 */
|
||||||
|
// AOCECurrencyInfo
|
||||||
|
|
||||||
|
int ParseAOCESpecificCurrency(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseRecordedCurrency, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, cur);
|
||||||
|
XSEQUENCE_OPT_1(ParseAOCEBillingId, ASN1_TAG_CONTEXT_SPECIFIC, 2, &cur->billingId);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCECurrencyInfoChoice(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseAOCESpecificCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, cur);
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1); // freeOfCharge
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCECurrencyInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseAOCECurrencyInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, cur);
|
||||||
|
XSEQUENCE_OPT_1(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &cur->chargeAssoc);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCEChargingUnitInfo
|
||||||
|
|
||||||
|
int ParseAOCESpecificChargingUnits(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseRecordedUnitsList, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, &chu->recordedUnits);
|
||||||
|
XSEQUENCE_OPT_1(ParseAOCEBillingId, ASN1_TAG_CONTEXT_SPECIFIC, 2, &chu->billingId);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCEChargingUnitInfoChoice(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseAOCESpecificChargingUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, chu);
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1); // freeOfCharge
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseAOCEChargingUnitInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCChargingUnit *chu)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseAOCEChargingUnitInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, chu);
|
||||||
|
XSEQUENCE_OPT_1(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &chu->chargeAssoc);
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOCEBillingId
|
||||||
|
|
||||||
|
int ParseAOCEBillingId(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *billingId)
|
||||||
|
{
|
||||||
|
return ParseEnum(pc, p, end, billingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currency
|
||||||
|
|
||||||
|
int ParseCurrency(struct asn1_parm *pc, u_char * p, u_char * end, char *currency)
|
||||||
|
{
|
||||||
|
struct asn1ParseString str;
|
||||||
|
|
||||||
|
str.buf = currency;
|
||||||
|
str.maxSize = 11; /* sizeof(struct FacAOCCurrency.currency) */
|
||||||
|
return ParseIA5String(pc, p, end, &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Amount
|
||||||
|
|
||||||
|
int ParseAmount(struct asn1_parm *pc, u_char * p, u_char * end, struct FacAOCCurrency *cur)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseCurrencyAmount, ASN1_TAG_CONTEXT_SPECIFIC, 1, &cur->currencyAmount);
|
||||||
|
XSEQUENCE_1(ParseMultiplier, ASN1_TAG_CONTEXT_SPECIFIC, 2, &cur->multiplier);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrencyAmount
|
||||||
|
|
||||||
|
int ParseCurrencyAmount(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *currencyAmount)
|
||||||
|
{
|
||||||
|
return ParseUnsignedInteger(pc, p, end, currencyAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiplier
|
||||||
|
|
||||||
|
int ParseMultiplier(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *multiplier)
|
||||||
|
{
|
||||||
|
return ParseEnum(pc, p, end, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeOfUnit
|
||||||
|
|
||||||
|
int ParseTypeOfUnit(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *typeOfUnit)
|
||||||
|
{
|
||||||
|
return ParseUnsignedInteger(pc, p, end, typeOfUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumberOfUnits
|
||||||
|
|
||||||
|
int ParseNumberOfUnits(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *numberOfUnits)
|
||||||
|
{
|
||||||
|
return ParseUnsignedInteger(pc, p, end, numberOfUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Charging Association
|
||||||
|
|
||||||
|
int ParseChargingAssociation(struct asn1_parm *pc, u_char * p, u_char * end, struct ChargingAssociation *chargeAssoc)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
struct FacPartyNumber partyNumber;
|
||||||
|
|
||||||
|
partyNumber.LengthOfNumber = 0;
|
||||||
|
partyNumber.Number[0] = '\0';
|
||||||
|
|
||||||
|
XCHOICE_1(ParsePartyNumber_Full, ASN1_TAG_SEQUENCE, 0, &partyNumber);
|
||||||
|
|
||||||
|
if ((partyNumber.LengthOfNumber) && (partyNumber.LengthOfNumber <= 30)
|
||||||
|
&& (partyNumber.Number[0] != '\0'))
|
||||||
|
strncpy((char *)chargeAssoc->chargeNumber, (char *)partyNumber.Number, 30);
|
||||||
|
|
||||||
|
XCHOICE_1(ParseChargeIdentifier, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &chargeAssoc->chargeIdentifier);
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChargeIdentifier
|
||||||
|
|
||||||
|
int ParseChargeIdentifier(struct asn1_parm *pc, u_char * p, u_char * end, int *chargeIdentifier)
|
||||||
|
{
|
||||||
|
return ParseSignedInteger(pc, p, end, chargeIdentifier);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* $Id: asn1_basic_service.c,v 1.2 2006/08/16 14:15:52 nadi Exp $
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// Basic Service Elements EN 300 196-1 D.6
|
||||||
|
|
||||||
|
int ParseBasicService(struct asn1_parm *pc, u_char * p, u_char * end, __u32 *basicService)
|
||||||
|
{
|
||||||
|
return ParseEnum(pc, p, end, basicService);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,590 @@
|
||||||
|
/*
|
||||||
|
* ASN1 components for supplementary services
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include "diversion.h"
|
||||||
|
#include "ccbs.h"
|
||||||
|
#include "ect.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// Component EN 300 196-1 D.1
|
||||||
|
|
||||||
|
static const struct asn1OidConvert OIDConversion[] = {
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
/*
|
||||||
|
* Note the first value in oid.values[] is really the first two
|
||||||
|
* OID subidentifiers. They are compressed using this formula:
|
||||||
|
* First_Value = (First_Subidentifier * 40) + Second_Subidentifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* {ccitt(0) identified-organization(4) etsi(0) 359 operations-and-errors(1)} */
|
||||||
|
{ FacOIDBase_CCBS, { 4, { 4, 0, 359, 1 } } },
|
||||||
|
|
||||||
|
/* {ccitt(0) identified-organization(4) etsi(0) 359 private-networks-operations-and-errors(2)} */
|
||||||
|
{ FacOIDBase_CCBS_T, { 4, { 4, 0, 359, 2 } } },
|
||||||
|
|
||||||
|
/* {ccitt(0) identified-organization(4) etsi(0) 1065 operations-and-errors(1)} */
|
||||||
|
{ FacOIDBase_CCNR, { 4, { 4, 0, 1065, 1 } } },
|
||||||
|
|
||||||
|
/* {ccitt(0) identified-organization(4) etsi(0) 1065 private-networks-operations-and-errors(2)} */
|
||||||
|
{ FacOIDBase_CCNR_T, { 4, { 4, 0, 1065, 2 } } },
|
||||||
|
|
||||||
|
/* {itu-t(0) identified-organization(4) etsi(0) 196 status-request-procedure(9)} */
|
||||||
|
{ FacOIDBase_StatusRequest, { 4, { 4, 0, 196, 9 } } },
|
||||||
|
|
||||||
|
/* {ccitt(0) identified-organization(4) etsi(0) 369 operations-and-errors(1)} */
|
||||||
|
{ FacOIDBase_ECT, { 4, { 4, 0, 369, 1 } } },
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct asn1OidConvert *FindOidByOidValue(int length, const __u16 oidValues[])
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
for (index = 0; index < sizeof(OIDConversion) / sizeof(OIDConversion[0]); ++index) {
|
||||||
|
if (OIDConversion[index].oid.numValues == length
|
||||||
|
&& memcmp(OIDConversion[index].oid.value, oidValues, length * sizeof(oidValues[0])) == 0) {
|
||||||
|
return &OIDConversion[index];
|
||||||
|
}
|
||||||
|
} /* end for */
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
} /* end FindOidByOidValue() */
|
||||||
|
|
||||||
|
const struct asn1OidConvert *FindOidByEnum(__u16 value)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
for (index = 0; index < sizeof(OIDConversion) / sizeof(OIDConversion[0]); ++index) {
|
||||||
|
if (FAC_OID_BASE(OIDConversion[index].baseCode) <= value && value < FAC_OID_BASE(OIDConversion[index].baseCode + 1)) {
|
||||||
|
return &OIDConversion[index];
|
||||||
|
}
|
||||||
|
} /* end for */
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
} /* end FindOidByEnum() */
|
||||||
|
|
||||||
|
__u16 ConvertOidToEnum(const struct asn1Oid * oid, __u16 errorValue)
|
||||||
|
{
|
||||||
|
const struct asn1OidConvert *convert;
|
||||||
|
__u16 enumValue;
|
||||||
|
|
||||||
|
enumValue = errorValue;
|
||||||
|
if (oid->numValues) {
|
||||||
|
convert = FindOidByOidValue(oid->numValues - 1, oid->value);
|
||||||
|
if (convert) {
|
||||||
|
enumValue = FAC_OID_BASE(convert->baseCode) + oid->value[oid->numValues - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumValue;
|
||||||
|
} /* end ConvertOidToEnum() */
|
||||||
|
|
||||||
|
int ConvertEnumToOid(struct asn1Oid *oid, __u16 enumValue)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
const struct asn1OidConvert *convert;
|
||||||
|
|
||||||
|
status = 0; /* Assume failure */
|
||||||
|
convert = FindOidByEnum(enumValue);
|
||||||
|
if (convert) {
|
||||||
|
*oid = convert->oid;
|
||||||
|
if (oid->numValues < sizeof(oid->value) / sizeof(oid->value[0])) {
|
||||||
|
oid->value[oid->numValues] = enumValue - FAC_OID_BASE(convert->baseCode);
|
||||||
|
++oid->numValues;
|
||||||
|
status = 1; /* successful */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
} /* end ConvertEnumToOid() */
|
||||||
|
|
||||||
|
static int ParseOperationOid(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *operationValue)
|
||||||
|
{
|
||||||
|
struct asn1Oid operationOid;
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
CallASN1(rval, p, end, ParseOid(pc, p, end, &operationOid));
|
||||||
|
*operationValue = ConvertOidToEnum(&operationOid, Fac_None);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
} /* end ParseOperationOid() */
|
||||||
|
|
||||||
|
static int ParseOperationValue(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *operationValue)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseUnsignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, operationValue);
|
||||||
|
XCHOICE_1(ParseOperationOid, ASN1_TAG_OBJECT_IDENTIFIER, ASN1_NOT_TAGGED, operationValue);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseInvokeComponent(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
signed int invokeId;
|
||||||
|
signed int linkedId;
|
||||||
|
unsigned int operationValue;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
pc->comp = CompInvoke;
|
||||||
|
XSEQUENCE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
|
||||||
|
pc->u.inv.invokeId = invokeId;
|
||||||
|
XSEQUENCE_OPT_1(ParseSignedInteger, ASN1_TAG_CONTEXT_SPECIFIC, 0, &linkedId);
|
||||||
|
XSEQUENCE_1(ParseOperationValue, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &operationValue);
|
||||||
|
pc->u.inv.operationValue = operationValue;
|
||||||
|
|
||||||
|
switch (operationValue) {
|
||||||
|
/* Diversion support */
|
||||||
|
case Fac_Begin3PTY:
|
||||||
|
case Fac_End3PTY:
|
||||||
|
/* No additional invoke parameters */
|
||||||
|
break;
|
||||||
|
case Fac_ActivationDiversion:
|
||||||
|
XSEQUENCE_1(ParseActivationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.ActivationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_DeactivationDiversion:
|
||||||
|
XSEQUENCE_1(ParseDeactivationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.DeactivationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_ActivationStatusNotificationDiv:
|
||||||
|
XSEQUENCE_1(ParseActivationStatusNotificationDiv, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.inv.o.ActivationStatusNotificationDiv);
|
||||||
|
break;
|
||||||
|
case Fac_DeactivationStatusNotificationDiv:
|
||||||
|
XSEQUENCE_1(ParseDeactivationStatusNotificationDiv, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.inv.o.DeactivationStatusNotificationDiv);
|
||||||
|
break;
|
||||||
|
case Fac_InterrogationDiversion:
|
||||||
|
XSEQUENCE_1(ParseInterrogationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.inv.o.InterrogationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_DiversionInformation:
|
||||||
|
XSEQUENCE_1(ParseDiversionInformation, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.DiversionInformation);
|
||||||
|
break;
|
||||||
|
case Fac_CallDeflection:
|
||||||
|
XSEQUENCE_1(ParseCallDeflection, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CallDeflection);
|
||||||
|
break;
|
||||||
|
case Fac_CallRerouteing:
|
||||||
|
XSEQUENCE_1(ParseCallRerouteing, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CallRerouteing);
|
||||||
|
break;
|
||||||
|
case Fac_InterrogateServedUserNumbers:
|
||||||
|
/* No additional invoke parameters */
|
||||||
|
break;
|
||||||
|
case Fac_DivertingLegInformation1:
|
||||||
|
XSEQUENCE_1(ParseDivertingLegInformation1, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.inv.o.DivertingLegInformation1);
|
||||||
|
break;
|
||||||
|
case Fac_DivertingLegInformation2:
|
||||||
|
XSEQUENCE_1(ParseDivertingLegInformation2, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.inv.o.DivertingLegInformation2);
|
||||||
|
break;
|
||||||
|
case Fac_DivertingLegInformation3:
|
||||||
|
XSEQUENCE_1(ParseDivertingLegInformation3, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.inv.o.DivertingLegInformation3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ECT support */
|
||||||
|
case Fac_EctExecute:
|
||||||
|
/* No additional invoke parameters */
|
||||||
|
break;
|
||||||
|
case Fac_ExplicitEctExecute:
|
||||||
|
XSEQUENCE_1(ParseExplicitEctExecute, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.ExplicitEctExecute);
|
||||||
|
break;
|
||||||
|
case Fac_RequestSubaddress:
|
||||||
|
/* No additional invoke parameters */
|
||||||
|
break;
|
||||||
|
case Fac_SubaddressTransfer:
|
||||||
|
XSEQUENCE_1(ParseSubaddressTransfer, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.SubaddressTransfer);
|
||||||
|
break;
|
||||||
|
case Fac_EctLinkIdRequest:
|
||||||
|
/* No additional invoke parameters */
|
||||||
|
break;
|
||||||
|
case Fac_EctInform:
|
||||||
|
XSEQUENCE_1(ParseEctInform, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.EctInform);
|
||||||
|
break;
|
||||||
|
case Fac_EctLoopTest:
|
||||||
|
XSEQUENCE_1(ParseEctLoopTest, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.EctLoopTest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* AOC support */
|
||||||
|
#if 0
|
||||||
|
case Fac_ChargingRequest:
|
||||||
|
case Fac_AOCSCurrency:
|
||||||
|
case Fac_AOCSSpecialArr:
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case Fac_AOCDCurrency:
|
||||||
|
XSEQUENCE_1(ParseAOCDCurrency, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.AOCcur);
|
||||||
|
break;
|
||||||
|
case Fac_AOCDChargingUnit:
|
||||||
|
XSEQUENCE_1(ParseAOCDChargingUnit, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.AOCchu);
|
||||||
|
break;
|
||||||
|
case Fac_AOCECurrency:
|
||||||
|
XSEQUENCE_1(ParseAOCECurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.AOCcur);
|
||||||
|
break;
|
||||||
|
case Fac_AOCEChargingUnit:
|
||||||
|
XSEQUENCE_1(ParseAOCEChargingUnit, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.AOCchu);
|
||||||
|
break;
|
||||||
|
case Fac_StatusRequest:
|
||||||
|
XSEQUENCE_1(ParseStatusRequest, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.StatusRequest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CCBS/CCNR support */
|
||||||
|
case Fac_CallInfoRetain:
|
||||||
|
XSEQUENCE_1(ParseCallInfoRetain, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.CallInfoRetain);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRequest:
|
||||||
|
XSEQUENCE_1(ParseCCBSRequest, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSDeactivate:
|
||||||
|
XSEQUENCE_1(ParseCCBSDeactivate, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSDeactivate);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSInterrogate:
|
||||||
|
XSEQUENCE_1(ParseCCBSInterrogate, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSInterrogate);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSErase:
|
||||||
|
XSEQUENCE_1(ParseCCBSErase, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSErase);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRemoteUserFree:
|
||||||
|
XSEQUENCE_1(ParseCCBSRemoteUserFree, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSRemoteUserFree);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSCall:
|
||||||
|
XSEQUENCE_1(ParseCCBSCall, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSCall);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStatusRequest:
|
||||||
|
XSEQUENCE_1(ParseCCBSStatusRequest, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSStatusRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSBFree:
|
||||||
|
XSEQUENCE_1(ParseCCBSBFree, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSBFree);
|
||||||
|
break;
|
||||||
|
case Fac_EraseCallLinkageID:
|
||||||
|
XSEQUENCE_1(ParseEraseCallLinkageID, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.EraseCallLinkageID);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStopAlerting:
|
||||||
|
XSEQUENCE_1(ParseCCBSStopAlerting, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBSStopAlerting);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRRequest:
|
||||||
|
XSEQUENCE_1(ParseCCNRRequest, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.inv.o.CCNRRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRInterrogate:
|
||||||
|
XSEQUENCE_1(ParseCCNRInterrogate, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCNRInterrogate);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CCBS-T/CCNR-T support */
|
||||||
|
case Fac_CCBS_T_Call:
|
||||||
|
case Fac_CCBS_T_Suspend:
|
||||||
|
case Fac_CCBS_T_Resume:
|
||||||
|
case Fac_CCBS_T_RemoteUserFree:
|
||||||
|
case Fac_CCBS_T_Available:
|
||||||
|
/* No additional invoke parameters */
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Request:
|
||||||
|
XSEQUENCE_1(ParseCCBS_T_Request, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCBS_T_Request);
|
||||||
|
break;
|
||||||
|
case Fac_CCNR_T_Request:
|
||||||
|
XSEQUENCE_1(ParseCCNR_T_Request, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.CCNR_T_Request);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseReturnResultComponentSequence(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseOperationValue, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.operationValue);
|
||||||
|
pc->u.retResult.operationValuePresent = 1;
|
||||||
|
|
||||||
|
switch (pc->u.retResult.operationValue) {
|
||||||
|
/* 3PTY */
|
||||||
|
case Fac_Begin3PTY:
|
||||||
|
case Fac_End3PTY:
|
||||||
|
/* No additional result parameters */
|
||||||
|
break;
|
||||||
|
/* Diversion support */
|
||||||
|
case Fac_ActivationDiversion:
|
||||||
|
case Fac_DeactivationDiversion:
|
||||||
|
/* No additional result parameters */
|
||||||
|
break;
|
||||||
|
case Fac_InterrogationDiversion:
|
||||||
|
XSEQUENCE_1(ParseInterrogationDiversion_RES, ASN1_TAG_SET, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.retResult.o.InterrogationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_CallDeflection:
|
||||||
|
case Fac_CallRerouteing:
|
||||||
|
/* No additional result parameters */
|
||||||
|
break;
|
||||||
|
case Fac_InterrogateServedUserNumbers:
|
||||||
|
XSEQUENCE_1(ParseInterrogateServedUserNumbers_RES, ASN1_TAG_SET, ASN1_NOT_TAGGED,
|
||||||
|
&pc->u.retResult.o.InterrogateServedUserNumbers);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ECT support */
|
||||||
|
case Fac_EctLinkIdRequest:
|
||||||
|
XSEQUENCE_1(ParseEctLinkIdRequest_RES, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.o.EctLinkIdRequest);
|
||||||
|
break;
|
||||||
|
case Fac_EctLoopTest:
|
||||||
|
XSEQUENCE_1(ParseEctLoopTest_RES, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.o.EctLoopTest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Fac_StatusRequest:
|
||||||
|
XSEQUENCE_1(ParseStatusRequest_RES, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.o.StatusRequest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CCBS/CCNR support */
|
||||||
|
case Fac_CCBSDeactivate:
|
||||||
|
/* No additional result parameters */
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStatusRequest:
|
||||||
|
XSEQUENCE_1(ParseCCBSStatusRequest_RES, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCBSStatusRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRequest:
|
||||||
|
XSEQUENCE_1(ParseCCBSRequest_RES, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCBSRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSInterrogate:
|
||||||
|
XSEQUENCE_1(ParseCCBSInterrogate_RES, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCBSInterrogate);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRRequest:
|
||||||
|
XSEQUENCE_1(ParseCCNRRequest_RES, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCNRRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRInterrogate:
|
||||||
|
XSEQUENCE_1(ParseCCNRInterrogate_RES, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCNRInterrogate);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CCBS-T/CCNR-T support */
|
||||||
|
case Fac_CCBS_T_Request:
|
||||||
|
XSEQUENCE_1(ParseCCBS_T_Request_RES, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCBS_T_Request);
|
||||||
|
break;
|
||||||
|
case Fac_CCNR_T_Request:
|
||||||
|
XSEQUENCE_1(ParseCCNR_T_Request_RES, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &pc->u.retResult.o.CCNR_T_Request);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseReturnResultComponent(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
signed int invokeId;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
pc->comp = CompReturnResult;
|
||||||
|
XSEQUENCE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
|
||||||
|
pc->u.retResult.invokeId = invokeId;
|
||||||
|
pc->u.retResult.operationValuePresent = 0;
|
||||||
|
XSEQUENCE_OPT(ParseReturnResultComponentSequence, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseErrorOid(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *errorValue)
|
||||||
|
{
|
||||||
|
struct asn1Oid errorOid;
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
CallASN1(rval, p, end, ParseOid(pc, p, end, &errorOid));
|
||||||
|
*errorValue = ConvertOidToEnum(&errorOid, FacError_Unknown);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
} /* end ParseErrorOid() */
|
||||||
|
|
||||||
|
static int ParseErrorValue(struct asn1_parm *pc, u_char * p, u_char * end, unsigned int *errorValue)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseUnsignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, errorValue);
|
||||||
|
XCHOICE_1(ParseErrorOid, ASN1_TAG_OBJECT_IDENTIFIER, ASN1_NOT_TAGGED, errorValue);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseReturnErrorComponent(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
int invokeId;
|
||||||
|
unsigned int errorValue;
|
||||||
|
const char *error;
|
||||||
|
char msg[20];
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
pc->comp = CompReturnError;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
|
||||||
|
XSEQUENCE_1(ParseErrorValue, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &errorValue);
|
||||||
|
|
||||||
|
pc->u.retError.invokeId = invokeId;
|
||||||
|
pc->u.retError.errorValue = errorValue;
|
||||||
|
|
||||||
|
switch (errorValue) {
|
||||||
|
case FacError_Gen_NotSubscribed:
|
||||||
|
error = "not subscribed";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_NotAvailable:
|
||||||
|
error = "not available";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_NotImplemented:
|
||||||
|
error = "not implemented";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_InvalidServedUserNr:
|
||||||
|
error = "invalid served user nr";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_InvalidCallState:
|
||||||
|
error = "invalid call state";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_BasicServiceNotProvided:
|
||||||
|
error = "basic service not provided";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_NotIncomingCall:
|
||||||
|
error = "not incoming call";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_SupplementaryServiceInteractionNotAllowed:
|
||||||
|
error = "supplementary service interaction not allowed";
|
||||||
|
break;
|
||||||
|
case FacError_Gen_ResourceUnavailable:
|
||||||
|
error = "resource unavailable";
|
||||||
|
break;
|
||||||
|
case FacError_Div_InvalidDivertedToNr:
|
||||||
|
error = "invalid diverted-to nr";
|
||||||
|
break;
|
||||||
|
case FacError_Div_SpecialServiceNr:
|
||||||
|
error = "special service nr";
|
||||||
|
break;
|
||||||
|
case FacError_Div_DiversionToServedUserNr:
|
||||||
|
error = "diversion to served user nr";
|
||||||
|
break;
|
||||||
|
case FacError_Div_IncomingCallAccepted:
|
||||||
|
error = "incoming call accepted";
|
||||||
|
break;
|
||||||
|
case FacError_Div_NumberOfDiversionsExceeded:
|
||||||
|
error = "number of diversions exceeded";
|
||||||
|
break;
|
||||||
|
case FacError_Div_NotActivated:
|
||||||
|
error = "not activated";
|
||||||
|
break;
|
||||||
|
case FacError_Div_RequestAlreadyAccepted:
|
||||||
|
error = "request already accepted";
|
||||||
|
break;
|
||||||
|
case FacError_AOC_NoChargingInfoAvailable:
|
||||||
|
error = "no charging info available";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_InvalidCallLinkageID:
|
||||||
|
error = "invalid call linkage id";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_InvalidCCBSReference:
|
||||||
|
error = "invalid ccbs reference";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_T_LongTermDenial:
|
||||||
|
case FacError_CCBS_LongTermDenial:
|
||||||
|
error = "long term denial";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_T_ShortTermDenial:
|
||||||
|
case FacError_CCBS_ShortTermDenial:
|
||||||
|
error = "short term denial";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_IsAlreadyActivated:
|
||||||
|
error = "ccbs is already activated";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_AlreadyAccepted:
|
||||||
|
error = "already accepted";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_OutgoingCCBSQueueFull:
|
||||||
|
error = "outgoing ccbs queue full";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_CallFailureReasonNotBusy:
|
||||||
|
error = "call failure reason not busy";
|
||||||
|
break;
|
||||||
|
case FacError_CCBS_NotReadyForCall:
|
||||||
|
error = "not ready for call";
|
||||||
|
break;
|
||||||
|
case FacError_Unknown:
|
||||||
|
error = "unknown OID error code";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(msg, "(%d)", errorValue);
|
||||||
|
error = msg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprint(DBGM_ASN1_DEC, "Decoded-Error: %s\n", error);
|
||||||
|
return p - beg;
|
||||||
|
} /* end of ParseReturnErrorComponent() */
|
||||||
|
|
||||||
|
int ParseProblemValue(struct asn1_parm *pc, u_char * p, u_char * end, asn1Problem prob)
|
||||||
|
{
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
pc->u.reject.problem = prob;
|
||||||
|
rval = ParseUnsignedInteger(pc, p, end, &pc->u.reject.problemValue);
|
||||||
|
dprint(DBGM_ASN1_DEC, "ParseProblemValue: %d %d, rval:%d\n", prob, pc->u.reject.problemValue, rval);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseRejectProblem(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE_1(ParseProblemValue, ASN1_TAG_CONTEXT_SPECIFIC, 0, GeneralP);
|
||||||
|
XCHOICE_1(ParseProblemValue, ASN1_TAG_CONTEXT_SPECIFIC, 1, InvokeP);
|
||||||
|
XCHOICE_1(ParseProblemValue, ASN1_TAG_CONTEXT_SPECIFIC, 2, ReturnResultP);
|
||||||
|
XCHOICE_1(ParseProblemValue, ASN1_TAG_CONTEXT_SPECIFIC, 3, ReturnErrorP);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseRejectInvokeId(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
pc->u.reject.invokeIdPresent = 1;
|
||||||
|
XCHOICE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &pc->u.reject.invokeId);
|
||||||
|
|
||||||
|
pc->u.reject.invokeIdPresent = 0;
|
||||||
|
pc->u.reject.invokeId = 0;
|
||||||
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED);
|
||||||
|
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseRejectComponent(struct asn1_parm *pc, u_char * p, u_char * end, int dummy)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
pc->comp = CompReject;
|
||||||
|
|
||||||
|
XSEQUENCE(ParseRejectInvokeId, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
|
||||||
|
if (pc->u.reject.invokeIdPresent) {
|
||||||
|
dprint(DBGM_ASN1_DEC, "ParseRejectComponent: invokeId %d\n", pc->u.reject.invokeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSEQUENCE(ParseRejectProblem, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseComponent(struct asn1_parm *pc, u_char * p, u_char * end)
|
||||||
|
{
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XCHOICE(ParseInvokeComponent, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1);
|
||||||
|
XCHOICE(ParseReturnResultComponent, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 2);
|
||||||
|
XCHOICE(ParseReturnErrorComponent, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 3);
|
||||||
|
XCHOICE(ParseRejectComponent, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 4);
|
||||||
|
XCHOICE_DEFAULT;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,403 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Explicit Call Transfer (ECT) Supplementary Services ETS 300 369-1
|
||||||
|
*
|
||||||
|
* ECT Facility ie encode/decode
|
||||||
|
*
|
||||||
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include "ect.h"
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the EctExecute facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param EctExecute Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacEctExecute(__u8 * Dest, const struct asn1_parm *pc, const void *val)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_EctExecute);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacEctExecute() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the ExplicitEctExecute facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param ExplicitEctExecute Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacExplicitEctExecute(__u8 * Dest, const struct asn1_parm *pc, const struct FacExplicitEctExecute *ExplicitEctExecute)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_ExplicitEctExecute);
|
||||||
|
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, ExplicitEctExecute->LinkID);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacExplicitEctExecute() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the ExplicitEctExecute invoke argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param ExplicitEctExecute Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseExplicitEctExecute(struct asn1_parm *pc, u_char * p, u_char * end, struct FacExplicitEctExecute *ExplicitEctExecute)
|
||||||
|
{
|
||||||
|
int LinkID;
|
||||||
|
int ret;
|
||||||
|
u_char *beg;
|
||||||
|
|
||||||
|
beg = p;
|
||||||
|
XSEQUENCE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &LinkID);
|
||||||
|
ExplicitEctExecute->LinkID = LinkID;
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseExplicitEctExecute() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the RequestSubaddress facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param RequestSubaddress Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacRequestSubaddress(__u8 * Dest, const struct asn1_parm *pc, const void *val)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_RequestSubaddress);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacRequestSubaddress() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the SubaddressTransfer facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param SubaddressTransfer Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacSubaddressTransfer(__u8 * Dest, const struct asn1_parm *pc, const struct FacSubaddressTransfer *SubaddressTransfer)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_SubaddressTransfer);
|
||||||
|
|
||||||
|
p += encodePartySubaddress_Full(p, &SubaddressTransfer->Subaddress);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacSubaddressTransfer() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the SubaddressTransfer invoke argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param SubaddressTransfer Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseSubaddressTransfer(struct asn1_parm *pc, u_char * p, u_char * end, struct FacSubaddressTransfer *SubaddressTransfer)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u_char *beg;
|
||||||
|
|
||||||
|
beg = p;
|
||||||
|
XSEQUENCE_1(ParsePartySubaddress_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &SubaddressTransfer->Subaddress);
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseSubaddressTransfer() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the EctLinkIdRequest facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param EctLinkIdRequest Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacEctLinkIdRequest(__u8 * Dest, const struct asn1_parm *pc, const struct FacEctLinkIdRequest_RES *EctLinkIdRequest)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *SeqStart;
|
||||||
|
|
||||||
|
switch (pc->comp) {
|
||||||
|
case CompInvoke:
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_EctLinkIdRequest);
|
||||||
|
|
||||||
|
/* No arguments */
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
case CompReturnResult:
|
||||||
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
||||||
|
|
||||||
|
SeqStart = p;
|
||||||
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &SeqStart[2];
|
||||||
|
|
||||||
|
p += encodeOperationValue(p, Fac_EctLinkIdRequest);
|
||||||
|
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.o.EctLinkIdRequest.LinkID);
|
||||||
|
|
||||||
|
/* sequence Length */
|
||||||
|
SeqStart[1] = p - &SeqStart[2];
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length = -1;
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacEctLinkIdRequest() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the EctLinkIdRequest result parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse parameters
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param EctLinkIdRequest Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseEctLinkIdRequest_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctLinkIdRequest_RES *EctLinkIdRequest)
|
||||||
|
{
|
||||||
|
int LinkID;
|
||||||
|
int ret;
|
||||||
|
u_char *beg;
|
||||||
|
|
||||||
|
beg = p;
|
||||||
|
XSEQUENCE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &LinkID);
|
||||||
|
EctLinkIdRequest->LinkID = LinkID;
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseEctLinkIdRequest_RES() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the EctInform facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param EctInform Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacEctInform(__u8 * Dest, const struct asn1_parm *pc, const struct FacEctInform *EctInform)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *SeqStart;
|
||||||
|
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_EctInform);
|
||||||
|
|
||||||
|
SeqStart = p;
|
||||||
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &SeqStart[2];
|
||||||
|
|
||||||
|
p += encodeEnum(p, ASN1_TAG_ENUM, EctInform->Status);
|
||||||
|
if (EctInform->RedirectionPresent) {
|
||||||
|
p += encodePresentedNumberUnscreened_Full(p, &EctInform->Redirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sequence Length */
|
||||||
|
SeqStart[1] = p - &SeqStart[2];
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacEctInform() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the EctInform invoke argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param EctInform Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseEctInform(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctInform *EctInform)
|
||||||
|
{
|
||||||
|
unsigned int Status;
|
||||||
|
INIT;
|
||||||
|
|
||||||
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Status);
|
||||||
|
EctInform->Status = Status;
|
||||||
|
if (p < end) {
|
||||||
|
XSEQUENCE_1(ParsePresentedNumberUnscreened_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &EctInform->Redirection);
|
||||||
|
EctInform->RedirectionPresent = 1;
|
||||||
|
} else {
|
||||||
|
EctInform->RedirectionPresent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseEctInform() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the EctLoopTest facility ie.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param EctLoopTest Information needed to encode in ie.
|
||||||
|
*
|
||||||
|
* \retval length on success.
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int encodeFacEctLoopTest(__u8 * Dest, const struct asn1_parm *pc, const struct FacEctLoopTest *EctLoopTest)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
__u8 *p;
|
||||||
|
__u8 *SeqStart;
|
||||||
|
|
||||||
|
switch (pc->comp) {
|
||||||
|
case CompInvoke:
|
||||||
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_EctLoopTest);
|
||||||
|
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, EctLoopTest->CallTransferID);
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
case CompReturnResult:
|
||||||
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
||||||
|
|
||||||
|
SeqStart = p;
|
||||||
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
||||||
|
p = &SeqStart[2];
|
||||||
|
|
||||||
|
p += encodeOperationValue(p, Fac_EctLoopTest);
|
||||||
|
|
||||||
|
p += encodeEnum(p, ASN1_TAG_ENUM, pc->u.retResult.o.EctLoopTest.LoopResult);
|
||||||
|
|
||||||
|
/* sequence Length */
|
||||||
|
SeqStart[1] = p - &SeqStart[2];
|
||||||
|
|
||||||
|
Length = encodeComponent_Length(Dest, p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length = -1;
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
} /* end encodeFacEctLoopTest() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the EctLoopTest invoke argument parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse arguments
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param EctLoopTest Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseEctLoopTest(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctLoopTest *EctLoopTest)
|
||||||
|
{
|
||||||
|
int CallTransferID;
|
||||||
|
int ret;
|
||||||
|
u_char *beg;
|
||||||
|
|
||||||
|
beg = p;
|
||||||
|
XSEQUENCE_1(ParseSignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &CallTransferID);
|
||||||
|
EctLoopTest->CallTransferID = CallTransferID;
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseEctLoopTest() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Parse the EctLoopTest result parameters.
|
||||||
|
*
|
||||||
|
* \param pc Complete component message storage data.
|
||||||
|
* \param p Starting buffer position to parse parameters
|
||||||
|
* \param end End buffer position that must not go past.
|
||||||
|
* \param EctLoopTest Parameter storage to fill.
|
||||||
|
*
|
||||||
|
* \retval length of buffer consumed
|
||||||
|
* \retval -1 on error.
|
||||||
|
*/
|
||||||
|
int ParseEctLoopTest_RES(struct asn1_parm *pc, u_char * p, u_char * end, struct FacEctLoopTest_RES *EctLoopTest)
|
||||||
|
{
|
||||||
|
unsigned int LoopResult;
|
||||||
|
int ret;
|
||||||
|
u_char *beg;
|
||||||
|
|
||||||
|
beg = p;
|
||||||
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &LoopResult);
|
||||||
|
EctLoopTest->LoopResult = LoopResult;
|
||||||
|
|
||||||
|
return p - beg;
|
||||||
|
} /* end ParseEctLoopTest_RES() */
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
/* end asn1_ect.c */
|
|
@ -0,0 +1,879 @@
|
||||||
|
/*
|
||||||
|
* fac.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006, Nadi Sarrar
|
||||||
|
* Nadi Sarrar <nadi@beronet.com>
|
||||||
|
*
|
||||||
|
* Portions of this file are based on the mISDN sources
|
||||||
|
* by Karsten Keil.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asn1.h"
|
||||||
|
#include "diversion.h"
|
||||||
|
#include <mISDN/q931.h>
|
||||||
|
#include "ccbs.h"
|
||||||
|
#include "ect.h"
|
||||||
|
#include "3pty.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define AOC_MAX_NUM_CHARGE_UNITS 0xFFFFFF
|
||||||
|
#define AOCE_CHARGE_UNIT_IE_LENGTH 17
|
||||||
|
#define AOCD_CHARGE_UNIT_IE_LENGTH 20
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SUPPLEMENTARY_SERVICE = 0x91, /* remote operations protocol */
|
||||||
|
} SERVICE_DISCRIMINATOR;
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the head of the Facility component message.
|
||||||
|
*
|
||||||
|
* \param p Start of the Facility message
|
||||||
|
* \param componentType Component-Type value
|
||||||
|
*
|
||||||
|
* \return Position for the next octet in the message
|
||||||
|
*/
|
||||||
|
__u8 *encodeComponent_Head(__u8 * p, enum asn1ComponentTag componentTag)
|
||||||
|
{
|
||||||
|
*p++ = IE_FACILITY; /* Facility IE identifier */
|
||||||
|
*p++ = 0; /* length -- not known yet */
|
||||||
|
*p++ = SUPPLEMENTARY_SERVICE; /* remote operations protocol */
|
||||||
|
*p++ = componentTag;
|
||||||
|
*p++ = 0; /* length -- not known yet */
|
||||||
|
return p;
|
||||||
|
} /* end encodeComponent_Head() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the head of the Facility component message
|
||||||
|
* with a length that can take a full __u8 value.
|
||||||
|
*
|
||||||
|
* \param p Start of the Facility message
|
||||||
|
* \param componentType Component-Type value
|
||||||
|
*
|
||||||
|
* \return Position for the next octet in the message
|
||||||
|
*/
|
||||||
|
__u8 *encodeComponent_Head_Long_u8(__u8 * p, enum asn1ComponentTag componentTag)
|
||||||
|
{
|
||||||
|
*p++ = IE_FACILITY; /* Facility IE identifier */
|
||||||
|
*p++ = 0; /* length -- not known yet */
|
||||||
|
*p++ = SUPPLEMENTARY_SERVICE; /* remote operations protocol */
|
||||||
|
*p++ = componentTag;
|
||||||
|
p += ASN1_NUM_OCTETS_LONG_LENGTH_u8; /* length -- not known yet */
|
||||||
|
return p;
|
||||||
|
} /* end encodeComponent_Head_Long_u8() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Fill in the final length for the Facility IE contents.
|
||||||
|
*
|
||||||
|
* \param msg Beginning of the Facility IE contents.
|
||||||
|
* \param p Pointer to the next octet of the Facility IE
|
||||||
|
* contents if there were more.
|
||||||
|
*
|
||||||
|
* \return Length of the Facility IE message
|
||||||
|
*/
|
||||||
|
int encodeComponent_Length(__u8 * msg, __u8 * p)
|
||||||
|
{
|
||||||
|
msg[4] = p - &msg[5];
|
||||||
|
msg[1] = p - &msg[2];
|
||||||
|
return msg[1] + 2;
|
||||||
|
} /* end encodeComponent_Length() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Fill in the final length for the Facility IE contents
|
||||||
|
* with a length that can take a full __u8 value.
|
||||||
|
*
|
||||||
|
* \param msg Beginning of the Facility IE contents.
|
||||||
|
* \param p Pointer to the next octet of the Facility IE
|
||||||
|
* contents if there were more.
|
||||||
|
*
|
||||||
|
* \return Length of the Facility IE message
|
||||||
|
*/
|
||||||
|
int encodeComponent_Length_Long_u8(__u8 * msg, __u8 * p)
|
||||||
|
{
|
||||||
|
encodeLen_Long_u8(&msg[4], p - &msg[4 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
||||||
|
msg[1] = p - &msg[2];
|
||||||
|
return msg[1] + 2;
|
||||||
|
} /* end encodeComponent_Length_Long_u8() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the Facility ie component operation-value.
|
||||||
|
*
|
||||||
|
* \param dest Where to put the operation-value
|
||||||
|
* \param operationValue enum operation-value to encode
|
||||||
|
*
|
||||||
|
* \return Length of the operation-value
|
||||||
|
*/
|
||||||
|
int encodeOperationValue(__u8 * dest, int operationValue)
|
||||||
|
{
|
||||||
|
struct asn1Oid operationOid;
|
||||||
|
|
||||||
|
if (IsEnumOid(operationValue)
|
||||||
|
&& ConvertEnumToOid(&operationOid, operationValue)) {
|
||||||
|
return encodeOid(dest, ASN1_TAG_OBJECT_IDENTIFIER, &operationOid);
|
||||||
|
} else {
|
||||||
|
return encodeInt(dest, ASN1_TAG_INTEGER, operationValue);
|
||||||
|
}
|
||||||
|
} /* end encodeOperationValue() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the Facility ie component error-value.
|
||||||
|
*
|
||||||
|
* \param dest Where to put the error-value
|
||||||
|
* \param errorValue enum error-value to encode
|
||||||
|
*
|
||||||
|
* \return Length of the error-value
|
||||||
|
*/
|
||||||
|
int encodeErrorValue(__u8 * dest, int errorValue)
|
||||||
|
{
|
||||||
|
return encodeOperationValue(dest, errorValue);
|
||||||
|
} /* end encodeErrorValue() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the common invoke component beginning
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param InvokeID
|
||||||
|
* \param OperationValue
|
||||||
|
*
|
||||||
|
* \return Position for the next octet in the message
|
||||||
|
*/
|
||||||
|
__u8 *encodeComponentInvoke_Head(__u8 * Dest, int InvokeID, enum Operation OperationValue)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Invoke);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, InvokeID);
|
||||||
|
//p += encodeInt(p, ASN1_TAG_CONTEXT_SPECIFIC | 0, LinkedID); /* Optional */
|
||||||
|
p += encodeOperationValue(p, OperationValue);
|
||||||
|
return p;
|
||||||
|
} /* end encodeComponentInvoke_Head() */
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \brief Encode the common invoke component beginning
|
||||||
|
* with a length that can take a full __u8 value.
|
||||||
|
*
|
||||||
|
* \param Dest Where to put the encoding
|
||||||
|
* \param InvokeID
|
||||||
|
* \param OperationValue
|
||||||
|
*
|
||||||
|
* \return Position for the next octet in the message
|
||||||
|
*/
|
||||||
|
__u8 *encodeComponentInvoke_Head_Long_u8(__u8 * Dest, int InvokeID, enum Operation OperationValue)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
p = encodeComponent_Head_Long_u8(Dest, asn1ComponentTag_Invoke);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, InvokeID);
|
||||||
|
//p += encodeInt(p, ASN1_TAG_CONTEXT_SPECIFIC | 0, LinkedID); /* Optional */
|
||||||
|
p += encodeOperationValue(p, OperationValue);
|
||||||
|
return p;
|
||||||
|
} /* end encodeComponentInvoke_Head_Long_u8() */
|
||||||
|
|
||||||
|
static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm *pc, int numberOfUnits)
|
||||||
|
{
|
||||||
|
/* Manually encoded ASN.1 */
|
||||||
|
|
||||||
|
unsigned char len = 0;
|
||||||
|
int i = 0;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
__u8 *p = dest;
|
||||||
|
|
||||||
|
if ((p != NULL) && (numberOfUnits <= AOC_MAX_NUM_CHARGE_UNITS)) {
|
||||||
|
if (numberOfUnits > 0xFFFF)
|
||||||
|
len = 3;
|
||||||
|
else if (numberOfUnits > 0xFF)
|
||||||
|
len = 2;
|
||||||
|
else
|
||||||
|
len = 1;
|
||||||
|
|
||||||
|
p[i++] = IE_FACILITY; // IE identifier
|
||||||
|
p[i++] = 0x00; // length -- not known yet
|
||||||
|
p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol
|
||||||
|
p[i++] = 0xa1; // invoke component
|
||||||
|
p[i++] = 0x00; // length -- not known yet
|
||||||
|
p[i++] = 0x02; // Invoke ID
|
||||||
|
p[i++] = 0x01; // InvokeId Length
|
||||||
|
p[i++] = pc->u.inv.invokeId;
|
||||||
|
p[i++] = 0x02; // Operation Tag
|
||||||
|
p[i++] = 0x01; // Tag Length
|
||||||
|
p[i++] = Fac_AOCDChargingUnit; // Operation Value
|
||||||
|
p[i++] = 0x30;
|
||||||
|
p[i++] = (0x09 + len); // Length
|
||||||
|
p[i++] = 0xa1; // APDU
|
||||||
|
p[i++] = (0x04 + len); // Length
|
||||||
|
p[i++] = 0x30;
|
||||||
|
p[i++] = (0x02 + len);
|
||||||
|
p[i++] = 0x02; // Operation Tag
|
||||||
|
p[i++] = 0x01; // AOC-D so Sub-Total
|
||||||
|
|
||||||
|
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
|
||||||
|
p[i] = numberOfUnits & 0xFF;
|
||||||
|
if (len > 1)
|
||||||
|
p[i+1] = (numberOfUnits >> 8) & 0xFF;
|
||||||
|
if (len > 2)
|
||||||
|
p[i+2] = (numberOfUnits >> 16) & 0xFF;
|
||||||
|
i += len;
|
||||||
|
|
||||||
|
p[i++] = 0x82;
|
||||||
|
p[i++] = 0x01;
|
||||||
|
p[i++] = 0x01;
|
||||||
|
|
||||||
|
p[1] = (AOCD_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
|
||||||
|
p[4] = p[1] - 3; // Invoke Component Length
|
||||||
|
result = p[1] + 2; // Total Length of IE
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int encodeAOCEChargingUnitOperation(__u8 * dest, const struct asn1_parm *pc, int numberOfUnits)
|
||||||
|
{
|
||||||
|
/* Manually encoded ASN.1 */
|
||||||
|
|
||||||
|
unsigned char len = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
__u8 *p = dest;
|
||||||
|
|
||||||
|
if ((p != NULL) && (numberOfUnits <= AOC_MAX_NUM_CHARGE_UNITS)) {
|
||||||
|
if (numberOfUnits > 0xFFFF)
|
||||||
|
len = 3;
|
||||||
|
else if (numberOfUnits > 0xFF)
|
||||||
|
len = 2;
|
||||||
|
else
|
||||||
|
len = 1;
|
||||||
|
|
||||||
|
p[i++] = IE_FACILITY; // IE identifier
|
||||||
|
p[i++] = 0x00; // length -- not known yet
|
||||||
|
p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol
|
||||||
|
p[i++] = 0xa1; // invoke component
|
||||||
|
p[i++] = 0x00; // length -- not known yet
|
||||||
|
p[i++] = 0x02; // Invoke ID
|
||||||
|
p[i++] = 0x01; // InvokeId Length
|
||||||
|
p[i++] = pc->u.inv.invokeId;
|
||||||
|
p[i++] = 0x02; // Operation Tag
|
||||||
|
p[i++] = 0x01; // Tag Length
|
||||||
|
p[i++] = Fac_AOCEChargingUnit; // Operation Value
|
||||||
|
p[i++] = 0xa1; // APDU
|
||||||
|
p[i++] = 0x30;
|
||||||
|
p[i++] = (0x09 + len); // Length
|
||||||
|
p[i++] = 0xa1; // APDU
|
||||||
|
p[i++] = (0x04 + len); // Length
|
||||||
|
p[i++] = 0x30;
|
||||||
|
p[i++] = (0x02 + len);
|
||||||
|
p[i++] = 0x02;
|
||||||
|
p[i++] = 0x02; // AOC-E so Total
|
||||||
|
|
||||||
|
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
|
||||||
|
p[i] = numberOfUnits & 0xFF;
|
||||||
|
if (len > 1)
|
||||||
|
p[i+1] = (numberOfUnits >> 8) & 0xFF;
|
||||||
|
if (len > 2)
|
||||||
|
p[i+2] = (numberOfUnits >> 16) & 0xFF;
|
||||||
|
i += len;
|
||||||
|
|
||||||
|
p[1] = (AOCE_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
|
||||||
|
p[4] = p[1] - 3; // Invoke Component Length
|
||||||
|
|
||||||
|
result = p[1] + 2; // Total Length of IE
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int encodeFacMcidIvokeRequest(__u8 * dest, const struct asn1_parm *pc)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int result = -1;
|
||||||
|
__u8 *p = dest;
|
||||||
|
|
||||||
|
if (p != NULL) {
|
||||||
|
p[i++] = IE_FACILITY; // IE identifier
|
||||||
|
p[i++] = 0x09; // length
|
||||||
|
p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol
|
||||||
|
p[i++] = 0xa1; // invoke component
|
||||||
|
p[i++] = 0x06; // Manually Encoding the MCID
|
||||||
|
p[i++] = 0x02; // Invoke ID
|
||||||
|
p[i++] = 0x01; // InvokeId Length
|
||||||
|
p[i++] = pc->u.inv.invokeId; // Invoke value
|
||||||
|
p[i++] = 0x02; // Operation Tag
|
||||||
|
p[i++] = 0x01; // Tag Length
|
||||||
|
p[i++] = Fac_MaliciousCallId; // Operation Value
|
||||||
|
|
||||||
|
result = p[1] + 2; // Total IE Length
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case Fac_RESULT:
|
||||||
|
len = encodeFacRESULT(dest, pc, &inv->o.RESULT);
|
||||||
|
break;
|
||||||
|
case Fac_ERROR:
|
||||||
|
len = encodeFacERROR(dest, pc, &inv->o.ERROR);
|
||||||
|
break;
|
||||||
|
case Fac_REJECT:
|
||||||
|
len = encodeFacREJECT(dest, pc, &inv->o.REJECT);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Facility IE Encoding
|
||||||
|
*/
|
||||||
|
static int encodeFacReturnResult(__u8 * dest, const struct asn1_parm *pc)
|
||||||
|
{
|
||||||
|
const struct asn1ReturnResult *res = &pc->u.retResult;
|
||||||
|
int len = -1;
|
||||||
|
char ops[20];
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
if (res->operationValuePresent)
|
||||||
|
sprintf(ops,"operation 0x%04x", res->operationValue);
|
||||||
|
else
|
||||||
|
sprintf(ops, "no operation value");
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_ENC, "Return result %s Id:%d start encoding\n", ops, res->invokeId);
|
||||||
|
if (res->operationValuePresent) {
|
||||||
|
switch (res->operationValue) {
|
||||||
|
case Fac_Begin3PTY:
|
||||||
|
len = encodeFacBegin3PTY(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_End3PTY:
|
||||||
|
len = encodeFacEnd3PTY(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_StatusRequest:
|
||||||
|
len = encodeFacStatusRequest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStatusRequest:
|
||||||
|
len = encodeFacCCBSStatusRequest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRequest:
|
||||||
|
len = encodeFacCCBSRequest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSInterrogate:
|
||||||
|
len = encodeFacCCBSInterrogate(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRRequest:
|
||||||
|
len = encodeFacCCNRRequest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRInterrogate:
|
||||||
|
len = encodeFacCCNRInterrogate(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Request:
|
||||||
|
len = encodeFacCCBS_T_Request(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCNR_T_Request:
|
||||||
|
len = encodeFacCCNR_T_Request(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_EctLinkIdRequest:
|
||||||
|
len = encodeFacEctLinkIdRequest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_EctLoopTest:
|
||||||
|
len = encodeFacEctLoopTest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_InterrogationDiversion:
|
||||||
|
len = encodeFacInterrogationDiversion(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_InterrogateServedUserNumbers:
|
||||||
|
len = encodeFacInterrogateServedUserNumbers(dest, pc, &res->o.InterrogateServedUserNumbers);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
eprint("ReturnResult Function %s not supported yet\n", ops);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = encodeComponent_Head(dest, asn1ComponentTag_Result);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, res->invokeId);
|
||||||
|
len = encodeComponent_Length(dest, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
eprint("Error on encoding ReturnResult %s\n", ops);
|
||||||
|
else {
|
||||||
|
dprint(DBGM_ASN1_ENC, "ReturnResult %s encoded in %d bytes\n", ops, len);
|
||||||
|
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Encode the ERROR response.
|
||||||
|
*
|
||||||
|
* \param dest Where to put the encoding
|
||||||
|
* \param error ERROR parameters
|
||||||
|
*
|
||||||
|
* \return Length of the encoding
|
||||||
|
*/
|
||||||
|
static int encodeFacReturnError(__u8 * dest, const struct asn1_parm *pc)
|
||||||
|
{
|
||||||
|
__u8 *p;
|
||||||
|
const struct asn1ReturnError *err = &pc->u.retError;
|
||||||
|
int len = -1;
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_ENC, "Return error Id:%d errorValue 0x%x start encoding\n", err->invokeId, err->errorValue);
|
||||||
|
|
||||||
|
|
||||||
|
p = encodeComponent_Head(dest, asn1ComponentTag_Error);
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, err->invokeId);
|
||||||
|
p += encodeErrorValue(p, err->errorValue);
|
||||||
|
len = encodeComponent_Length(dest, p);
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_ENC, "ReturnError encoded in %d bytes\n", len);
|
||||||
|
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ******************************************************************* */
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Encode the REJECT response.
|
||||||
|
*
|
||||||
|
* \param dest Where to put the encoding
|
||||||
|
* \param error REJECT parameters
|
||||||
|
*
|
||||||
|
* \return Length of the encoding
|
||||||
|
*/
|
||||||
|
static int encodeFacReject(__u8 * dest, const struct asn1_parm *pc)
|
||||||
|
{
|
||||||
|
const struct asn1Reject *rej = &pc->u.reject;
|
||||||
|
int len = -1;
|
||||||
|
char ids[16];
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
if (rej->invokeIdPresent)
|
||||||
|
sprintf(ids,"ID 0x%04x", rej->invokeId);
|
||||||
|
else
|
||||||
|
sprintf(ids, "no invoke ID");
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_ENC, "Reject %s problem %d value 0x%x start encoding\n", ids, rej->problem, rej->problemValue);
|
||||||
|
|
||||||
|
p = encodeComponent_Head(dest, asn1ComponentTag_Reject);
|
||||||
|
|
||||||
|
if (rej->invokeIdPresent)
|
||||||
|
p += encodeInt(p, ASN1_TAG_INTEGER, rej->invokeId);
|
||||||
|
else
|
||||||
|
p += encodeNull(p, ASN1_TAG_NULL);
|
||||||
|
|
||||||
|
p += encodeInt(p, ASN1_TAG_CONTEXT_SPECIFIC | rej->problem, rej->problemValue);
|
||||||
|
|
||||||
|
len = encodeComponent_Length(dest, p);
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_ENC, "Reject encoded in %d bytes\n", len);
|
||||||
|
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int encodeFacInvoke(__u8 * dest, const struct asn1_parm *pc)
|
||||||
|
{
|
||||||
|
const struct asn1Invoke *inv = &pc->u.inv;
|
||||||
|
int len = -1;
|
||||||
|
|
||||||
|
dprint(DBGM_ASN1_ENC, "Invoke operation 0x%x Id:%d start encoding\n", inv->operationValue, inv->invokeId);
|
||||||
|
switch (inv->operationValue) {
|
||||||
|
case Fac_None:
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Diversion support */
|
||||||
|
case Fac_ActivationDiversion:
|
||||||
|
len = encodeFacActivationDiversion(dest, pc, &inv->o.ActivationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_Begin3PTY:
|
||||||
|
len = encodeFacBegin3PTY(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_End3PTY:
|
||||||
|
len = encodeFacEnd3PTY(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_DeactivationDiversion:
|
||||||
|
len = encodeFacDeactivationDiversion(dest, pc, &inv->o.DeactivationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_ActivationStatusNotificationDiv:
|
||||||
|
len = encodeFacActivationStatusNotificationDiv(dest, pc, &inv->o.ActivationStatusNotificationDiv);
|
||||||
|
break;
|
||||||
|
case Fac_DeactivationStatusNotificationDiv:
|
||||||
|
len = encodeFacDeactivationStatusNotificationDiv(dest, pc, &inv->o.DeactivationStatusNotificationDiv);
|
||||||
|
break;
|
||||||
|
case Fac_InterrogationDiversion:
|
||||||
|
len = encodeFacInterrogationDiversion(dest, pc, &inv->o.InterrogationDiversion);
|
||||||
|
break;
|
||||||
|
case Fac_DiversionInformation:
|
||||||
|
len = encodeFacDiversionInformation(dest, pc, &inv->o.DiversionInformation);
|
||||||
|
break;
|
||||||
|
case Fac_CallDeflection:
|
||||||
|
len = encodeFacCallDeflection(dest, pc, &inv->o.CallDeflection);
|
||||||
|
break;
|
||||||
|
case Fac_CallRerouteing:
|
||||||
|
len = encodeFacCallRerouteing(dest, pc, &inv->o.CallRerouteing);
|
||||||
|
break;
|
||||||
|
case Fac_InterrogateServedUserNumbers:
|
||||||
|
len = encodeFacInterrogateServedUserNumbers(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_DivertingLegInformation1:
|
||||||
|
len = encodeFacDivertingLegInformation1(dest, pc, &inv->o.DivertingLegInformation1);
|
||||||
|
break;
|
||||||
|
case Fac_DivertingLegInformation2:
|
||||||
|
len = encodeFacDivertingLegInformation2(dest, pc, &inv->o.DivertingLegInformation2);
|
||||||
|
break;
|
||||||
|
case Fac_DivertingLegInformation3:
|
||||||
|
len = encodeFacDivertingLegInformation3(dest, pc, &inv->o.DivertingLegInformation3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ECT support */
|
||||||
|
case Fac_EctExecute:
|
||||||
|
len = encodeFacEctExecute(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_ExplicitEctExecute:
|
||||||
|
len = encodeFacExplicitEctExecute(dest, pc, &inv->o.ExplicitEctExecute);
|
||||||
|
break;
|
||||||
|
case Fac_RequestSubaddress:
|
||||||
|
len = encodeFacRequestSubaddress(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_SubaddressTransfer:
|
||||||
|
len = encodeFacSubaddressTransfer(dest, pc, &inv->o.SubaddressTransfer);
|
||||||
|
break;
|
||||||
|
case Fac_EctLinkIdRequest:
|
||||||
|
len = encodeFacEctLinkIdRequest(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_EctInform:
|
||||||
|
len = encodeFacEctInform(dest, pc, &inv->o.EctInform);
|
||||||
|
break;
|
||||||
|
case Fac_EctLoopTest:
|
||||||
|
len = encodeFacEctLoopTest(dest, pc, &inv->o.EctLoopTest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* AOC support */
|
||||||
|
case Fac_ChargingRequest:
|
||||||
|
case Fac_AOCSCurrency:
|
||||||
|
case Fac_AOCSSpecialArr:
|
||||||
|
case Fac_AOCDCurrency:
|
||||||
|
case Fac_AOCECurrency:
|
||||||
|
break;
|
||||||
|
case Fac_AOCDChargingUnit:
|
||||||
|
len = encodeAOCDChargingUnitOperation(dest, pc, inv->o.AOCchu.recordedUnits);
|
||||||
|
break;
|
||||||
|
case Fac_AOCEChargingUnit:
|
||||||
|
len = encodeAOCEChargingUnitOperation(dest, pc, inv->o.AOCchu.recordedUnits);
|
||||||
|
break;
|
||||||
|
/* Malicious Call Tag Support */
|
||||||
|
case Fac_MaliciousCallId:
|
||||||
|
len = encodeFacMcidIvokeRequest(dest, pc);
|
||||||
|
break;
|
||||||
|
case Fac_StatusRequest:
|
||||||
|
len = encodeFacStatusRequest(dest, pc, &inv->o.StatusRequest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CCBS/CCNR support */
|
||||||
|
case Fac_CallInfoRetain:
|
||||||
|
len = encodeFacCallInfoRetain(dest, pc, &inv->o.CallInfoRetain);
|
||||||
|
break;
|
||||||
|
case Fac_EraseCallLinkageID:
|
||||||
|
len = encodeFacEraseCallLinkageID(dest, pc, &inv->o.EraseCallLinkageID);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSDeactivate:
|
||||||
|
len = encodeFacCCBSDeactivate(dest, pc, &inv->o.CCBSDeactivate);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSErase:
|
||||||
|
len = encodeFacCCBSErase(dest, pc, &inv->o.CCBSErase);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRemoteUserFree:
|
||||||
|
len = encodeFacCCBSRemoteUserFree(dest, pc, &inv->o.CCBSRemoteUserFree);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSCall:
|
||||||
|
len = encodeFacCCBSCall(dest, pc, &inv->o.CCBSCall);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStatusRequest:
|
||||||
|
len = encodeFacCCBSStatusRequest(dest, pc, &inv->o.CCBSStatusRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSBFree:
|
||||||
|
len = encodeFacCCBSBFree(dest, pc, &inv->o.CCBSBFree);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStopAlerting:
|
||||||
|
len = encodeFacCCBSStopAlerting(dest, pc, &inv->o.CCBSStopAlerting);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRequest:
|
||||||
|
len = encodeFacCCBSRequest(dest, pc, &inv->o.CCBSRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCBSInterrogate:
|
||||||
|
len = encodeFacCCBSInterrogate(dest, pc, &inv->o.CCBSInterrogate);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRRequest:
|
||||||
|
len = encodeFacCCNRRequest(dest, pc, &inv->o.CCNRRequest);
|
||||||
|
break;
|
||||||
|
case Fac_CCNRInterrogate:
|
||||||
|
len = encodeFacCCNRInterrogate(dest, pc, &inv->o.CCNRInterrogate);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CCBS-T/CCNR-T support */
|
||||||
|
case Fac_CCBS_T_Call:
|
||||||
|
len = encodeFacCCBS_T_Call(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Suspend:
|
||||||
|
len = encodeFacCCBS_T_Suspend(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Resume:
|
||||||
|
len = encodeFacCCBS_T_Resume(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_RemoteUserFree:
|
||||||
|
len = encodeFacCCBS_T_RemoteUserFree(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Available:
|
||||||
|
len = encodeFacCCBS_T_Available(dest, pc, NULL);
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Request:
|
||||||
|
len = encodeFacCCBS_T_Request(dest, pc, &inv->o.CCBS_T_Request);
|
||||||
|
break;
|
||||||
|
case Fac_CCNR_T_Request:
|
||||||
|
len = encodeFacCCNR_T_Request(dest, pc, &inv->o.CCNR_T_Request);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
eprint("Function %d not supported yet\n", inv->operationValue);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len < 0)
|
||||||
|
eprint("Error on encoding function 0x%x\n", inv->operationValue);
|
||||||
|
else {
|
||||||
|
dprint(DBGM_ASN1_ENC, "Function 0x%x encoded in %d bytes\n", inv->operationValue, len);
|
||||||
|
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encodeFac(__u8 * dest, struct asn1_parm *ap)
|
||||||
|
{
|
||||||
|
int len = -1;
|
||||||
|
|
||||||
|
if (ap->Valid) {
|
||||||
|
switch (ap->comp) {
|
||||||
|
case CompInvoke:
|
||||||
|
len = encodeFacInvoke(dest, ap);
|
||||||
|
break;
|
||||||
|
case CompReturnResult:
|
||||||
|
len = encodeFacReturnResult(dest, ap);
|
||||||
|
break;
|
||||||
|
case CompReturnError:
|
||||||
|
len = encodeFacReturnError(dest, ap);
|
||||||
|
break;
|
||||||
|
case CompReject:
|
||||||
|
len = encodeFacReject(dest, ap);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
eprint("Unknown component 0x%x\n", ap->comp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
eprint("Facility struct component(%d) not marked as valid\n", ap->comp);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Facility IE Decoding
|
||||||
|
*/
|
||||||
|
int decodeFac(__u8 * src, struct asn1_parm *ap)
|
||||||
|
{
|
||||||
|
unsigned fac_len;
|
||||||
|
__u8 *end;
|
||||||
|
__u8 *p = src;
|
||||||
|
|
||||||
|
if (!p) {
|
||||||
|
goto _dec_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fac_len = *p++;
|
||||||
|
end = p + fac_len;
|
||||||
|
|
||||||
|
if (*p++ != SUPPLEMENTARY_SERVICE) {
|
||||||
|
goto _dec_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ap, 0, sizeof(*ap));
|
||||||
|
if (ParseComponent(ap, p, end) == -1) {
|
||||||
|
goto _dec_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ap->comp) {
|
||||||
|
case CompInvoke:
|
||||||
|
switch (ap->u.inv.operationValue) {
|
||||||
|
/* Diversion support */
|
||||||
|
case Fac_ActivationDiversion:
|
||||||
|
case Fac_DeactivationDiversion:
|
||||||
|
case Fac_ActivationStatusNotificationDiv:
|
||||||
|
case Fac_DeactivationStatusNotificationDiv:
|
||||||
|
case Fac_InterrogationDiversion:
|
||||||
|
case Fac_DiversionInformation:
|
||||||
|
case Fac_CallDeflection:
|
||||||
|
case Fac_CallRerouteing:
|
||||||
|
case Fac_InterrogateServedUserNumbers:
|
||||||
|
case Fac_DivertingLegInformation1:
|
||||||
|
case Fac_DivertingLegInformation2:
|
||||||
|
case Fac_DivertingLegInformation3:
|
||||||
|
/* ECT support */
|
||||||
|
case Fac_EctExecute:
|
||||||
|
case Fac_ExplicitEctExecute:
|
||||||
|
case Fac_RequestSubaddress:
|
||||||
|
case Fac_SubaddressTransfer:
|
||||||
|
case Fac_EctLinkIdRequest:
|
||||||
|
case Fac_EctInform:
|
||||||
|
case Fac_EctLoopTest:
|
||||||
|
/* AOC support */
|
||||||
|
case Fac_AOCDCurrency:
|
||||||
|
case Fac_AOCECurrency:
|
||||||
|
case Fac_AOCDChargingUnit:
|
||||||
|
case Fac_AOCEChargingUnit:
|
||||||
|
case Fac_StatusRequest:
|
||||||
|
/* CCBS/CCNR support */
|
||||||
|
case Fac_CallInfoRetain:
|
||||||
|
case Fac_EraseCallLinkageID:
|
||||||
|
case Fac_CCBSDeactivate:
|
||||||
|
case Fac_CCBSErase:
|
||||||
|
case Fac_CCBSRemoteUserFree:
|
||||||
|
case Fac_CCBSCall:
|
||||||
|
case Fac_CCBSStatusRequest:
|
||||||
|
case Fac_CCBSBFree:
|
||||||
|
case Fac_CCBSStopAlerting:
|
||||||
|
case Fac_CCBSRequest:
|
||||||
|
case Fac_CCBSInterrogate:
|
||||||
|
case Fac_CCNRRequest:
|
||||||
|
case Fac_CCNRInterrogate:
|
||||||
|
/* CCBS-T/CCNR-T support */
|
||||||
|
case Fac_CCBS_T_Call:
|
||||||
|
case Fac_CCBS_T_Suspend:
|
||||||
|
case Fac_CCBS_T_Resume:
|
||||||
|
case Fac_CCBS_T_RemoteUserFree:
|
||||||
|
case Fac_CCBS_T_Available:
|
||||||
|
case Fac_CCBS_T_Request:
|
||||||
|
case Fac_CCNR_T_Request:
|
||||||
|
ap->Valid = 1;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
eprint("Unknown invoke operation %x\n", ap->u.inv.operationValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
case CompReturnResult:
|
||||||
|
if (!ap->u.retResult.operationValuePresent) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (ap->u.retResult.operationValue) {
|
||||||
|
/* Diversion support */
|
||||||
|
case Fac_ActivationDiversion:
|
||||||
|
case Fac_DeactivationDiversion:
|
||||||
|
case Fac_InterrogationDiversion:
|
||||||
|
case Fac_CallDeflection:
|
||||||
|
case Fac_CallRerouteing:
|
||||||
|
case Fac_InterrogateServedUserNumbers:
|
||||||
|
ap->Valid = 1;
|
||||||
|
return 0;
|
||||||
|
case Fac_ActivationStatusNotificationDiv:
|
||||||
|
case Fac_DeactivationStatusNotificationDiv:
|
||||||
|
case Fac_DiversionInformation:
|
||||||
|
case Fac_DivertingLegInformation1:
|
||||||
|
case Fac_DivertingLegInformation2:
|
||||||
|
case Fac_DivertingLegInformation3:
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ECT support */
|
||||||
|
case Fac_EctExecute:
|
||||||
|
case Fac_ExplicitEctExecute:
|
||||||
|
case Fac_RequestSubaddress:
|
||||||
|
case Fac_SubaddressTransfer:
|
||||||
|
break;
|
||||||
|
case Fac_EctLinkIdRequest:
|
||||||
|
return 0;
|
||||||
|
case Fac_EctInform:
|
||||||
|
break;
|
||||||
|
case Fac_EctLoopTest:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* AOC support */
|
||||||
|
case Fac_ChargingRequest:
|
||||||
|
case Fac_AOCSCurrency:
|
||||||
|
case Fac_AOCSSpecialArr:
|
||||||
|
case Fac_AOCDCurrency:
|
||||||
|
case Fac_AOCDChargingUnit:
|
||||||
|
case Fac_AOCECurrency:
|
||||||
|
case Fac_AOCEChargingUnit:
|
||||||
|
break;
|
||||||
|
case Fac_StatusRequest:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* CCBS/CCNR support */
|
||||||
|
case Fac_CallInfoRetain:
|
||||||
|
case Fac_EraseCallLinkageID:
|
||||||
|
break;
|
||||||
|
case Fac_CCBSDeactivate:
|
||||||
|
return 0;
|
||||||
|
case Fac_CCBSErase:
|
||||||
|
case Fac_CCBSRemoteUserFree:
|
||||||
|
case Fac_CCBSCall:
|
||||||
|
break;
|
||||||
|
case Fac_CCBSStatusRequest:
|
||||||
|
return 0;
|
||||||
|
case Fac_CCBSBFree:
|
||||||
|
case Fac_CCBSStopAlerting:
|
||||||
|
break;
|
||||||
|
case Fac_CCBSRequest:
|
||||||
|
case Fac_CCBSInterrogate:
|
||||||
|
case Fac_CCNRRequest:
|
||||||
|
case Fac_CCNRInterrogate:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* CCBS-T/CCNR-T support */
|
||||||
|
case Fac_CCBS_T_Call:
|
||||||
|
case Fac_CCBS_T_Suspend:
|
||||||
|
case Fac_CCBS_T_Resume:
|
||||||
|
case Fac_CCBS_T_RemoteUserFree:
|
||||||
|
case Fac_CCBS_T_Available:
|
||||||
|
break;
|
||||||
|
case Fac_CCBS_T_Request:
|
||||||
|
case Fac_CCNR_T_Request:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
case CompReturnError:
|
||||||
|
ap->Valid = 1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
case CompReject:
|
||||||
|
ap->Valid = 1;
|
||||||
|
return 0;
|
||||||
|
} /* end switch */
|
||||||
|
|
||||||
|
_dec_err:
|
||||||
|
return -1;
|
||||||
|
} /* end decodeFac() */
|
Loading…
Reference in New Issue