Add mISDNuser to this project

This commit is contained in:
Andreas Eversberg 2022-03-27 16:28:34 +02:00
parent 7ebde07432
commit 4150cc3e67
45 changed files with 18531 additions and 0 deletions

1
.gitignore vendored
View File

@ -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

View File

@ -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)

View File

@ -9,5 +9,6 @@ SUBDIRS = \
libosmocc \ libosmocc \
libg711 \ libg711 \
libmisdn \ libmisdn \
libmisdnuser \
isdn isdn

View File

@ -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)

View File

@ -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;
}

View File

@ -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() */

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,5 @@
// to be compatible...
#define MISDN_AF_ISDN 34

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

159
src/libmisdnuser/misc/fsm.c Normal file
View File

@ -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);
}

View File

@ -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++;
}

View File

@ -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)&para);
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;
}

View File

@ -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() */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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() */