Compare commits

..

4 Commits

Author SHA1 Message Date
Kevin P. Fleming
109b8be22b remove CVS ignore lists
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.0.4@267 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-29 18:40:06 +00:00
Kevin P. Fleming
930c40d6be remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.0.4@266 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-29 18:39:18 +00:00
Kevin P. Fleming
087d530ae5 automatic tag renames
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.0.4@263 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-27 04:17:23 +00:00
Admin Commit
18181e796b This commit was manufactured by cvs2svn to create tag 'v1-0-4'.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/v1-0-4@178 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-01-14 05:14:27 +00:00
41 changed files with 2460 additions and 37845 deletions

View File

@@ -1 +0,0 @@
1.4.11

1113
ChangeLog

File diff suppressed because it is too large Load Diff

179
Makefile
View File

@@ -27,145 +27,56 @@
# Uncomment if you want libpri to count number of Q921/Q931 sent/received
#LIBPRI_COUNTERS=-DLIBPRI_COUNTERS
CC=gcc
GREP=grep
AWK=awk
OSARCH=$(shell uname -s)
PROC?=$(shell uname -m)
# SONAME version; should be changed on every ABI change
# please don't change it needlessly; it's perfectly fine to have a SONAME
# of 1.2 and a version of 1.4.x
SONAME:=1.4
PROC=$(shell uname -m)
TOBJS=testpri.o
T2OBJS=testprilib.o
STATIC_LIBRARY=libpri.a
DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
STATIC_OBJS= \
copy_string.o \
pri.o \
q921.o \
prisched.o \
q931.o \
pri_facility.o \
asn1_primitive.o \
rose.o \
rose_address.o \
rose_etsi_aoc.o \
rose_etsi_diversion.o \
rose_etsi_ect.o \
rose_other.o \
rose_q931.o \
rose_qsig_aoc.o \
rose_qsig_ct.o \
rose_qsig_diversion.o \
rose_qsig_mwi.o \
rose_qsig_name.o \
version.o
DYNAMIC_OBJS= \
copy_string.lo \
pri.lo \
q921.lo \
prisched.lo \
q931.lo \
pri_facility.lo \
asn1_primitive.lo \
rose.lo \
rose_address.lo \
rose_etsi_aoc.lo \
rose_etsi_diversion.lo \
rose_etsi_ect.lo \
rose_other.lo \
rose_q931.lo \
rose_qsig_aoc.lo \
rose_qsig_ct.lo \
rose_qsig_diversion.lo \
rose_qsig_mwi.lo \
rose_qsig_name.lo \
version.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) $(LIBPRI_OPT)
INSTALL_PREFIX=$(DESTDIR)
INSTALL_BASE=/usr
libdir?=$(INSTALL_BASE)/lib
SOFLAGS:=-Wl,-h$(DYNAMIC_LIBRARY)
LDCONFIG = /sbin/ldconfig
ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX XGNUX))
DYNAMIC_LIBRARY=libpri.so.1.0
STATIC_OBJS=pri.o q921.o prisched.o q931.o
DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
INSTALL_PREFIX=
ifeq (${OSARCH},Linux)
LDCONFIG_FLAGS=-n
else
ifeq (${OSARCH},FreeBSD)
LDCONFIG_FLAGS=-m
CFLAGS += -I../zaptel -I../zapata
INSTALL_BASE=/usr/local
endif
endif
ifeq (${OSARCH},SunOS)
CFLAGS += -DSOLARIS -I../zaptel-solaris
LDCONFIG =
LDCONFIG_FLAGS = \# # Trick to comment out the period in the command below
#INSTALL_PREFIX = /opt/asterisk # Uncomment out to install in standard Solaris location for 3rd party code
endif
export PRIVERSION
PRIVERSION:=$(shell GREP=$(GREP) AWK=$(AWK) build_tools/make_version .)
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
#This works for even old (2.96) versions of gcc and provides a small boost either way.
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesnt support it.
ifeq ($(PROC),sparc64)
PROC=ultrasparc
LIBPRI_OPT = -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
else
LIBPRI_OPT = -O2
CFLAGS += -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
endif
ifeq ($(CPUARCH),i686)
CFLAGS += -m32
SOFLAGS += -m32
endif
all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
all: depend $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
update:
@if [ -d .svn ]; then \
echo "Updating from Subversion..." ; \
fromrev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
svn update | tee update.out; \
torev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
echo "`date` Updated from revision $${fromrev} to $${torev}." >> update.log; \
rm -f .version; \
if [ `grep -c ^C update.out` -gt 0 ]; then \
echo ; echo "The following files have conflicts:" ; \
grep ^C update.out | cut -b4- ; \
fi ; \
rm -f update.out; \
else \
echo "Not under version control"; \
fi
@echo "Updating from CVS"
@cvs update -d
install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
mkdir -p $(INSTALL_PREFIX)$(libdir)
mkdir -p $(INSTALL_PREFIX)$(INSTALL_BASE)/include
ifneq (${OSARCH},SunOS)
install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
#if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi
else
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include -m 644 libpri.h
install -f $(INSTALL_PREFIX)$(libdir) -m 755 $(DYNAMIC_LIBRARY)
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
install -f $(INSTALL_PREFIX)$(libdir) -m 644 $(STATIC_LIBRARY)
endif
mkdir -p $(INSTALL_PREFIX)/usr/lib
mkdir -p $(INSTALL_PREFIX)/usr/include
install -m 644 libpri.h $(INSTALL_PREFIX)/usr/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)/usr/lib
if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then restorecon -v $(INSTALL_PREFIX)/$(INSTALL_BASE)/lib/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)/usr/lib ; ln -sf libpri.so.1 libpri.so )
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)/usr/lib
/sbin/ldconfig
uninstall:
@echo "Removing Libpri"
rm -f $(INSTALL_PREFIX)$(libdir)/libpri.so.$(SONAME)
rm -f $(INSTALL_PREFIX)$(libdir)/libpri.so
rm -f $(INSTALL_PREFIX)$(libdir)/libpri.a
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include/libpri.h
rm -f $(INSTALL_PREFIX)/usr/lib/libpri.so.1.0
rm -f $(INSTALL_PREFIX)/usr/lib/libpri.so
rm -f $(INSTALL_PREFIX)/usr/lib/libpri.a
rm -f $(INSTALL_PREFIX)/usr/include/libpri.h
pritest: pritest.o
$(CC) -o pritest pritest.o -L. -lpri -lzap $(CFLAGS)
@@ -177,43 +88,29 @@ testprilib: testprilib.o
$(CC) -o testprilib testprilib.o -L. -lpri -lpthread $(CFLAGS)
pridump: pridump.o
$(CC) -o pridump pridump.o -L. -lpri $(CFLAGS)
$(CC) -o pridump pridump.o -L. -lpri -lzap $(CFLAGS)
rosetest: rosetest.o
$(CC) -o rosetest rosetest.o -L. -lpri $(CFLAGS)
include .depend
MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
%.o: %.c
$(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $<
%.lo: %.c
$(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $<
%.lo : %.c
$(CC) -fPIC $(CFLAGS) -o $@ -c $<
$(STATIC_LIBRARY): $(STATIC_OBJS)
ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
ranlib $(STATIC_LIBRARY)
$(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
$(CC) -shared $(SOFLAGS) -o $@ $(DYNAMIC_OBJS)
$(LDCONFIG) $(LDCONFIG_FLAGS) .
ln -sf libpri.so.$(SONAME) libpri.so
version.c: FORCE
@build_tools/make_version_c > $@.tmp
@cmp -s $@.tmp $@ || mv $@.tmp $@
@rm -f $@.tmp
$(CC) -shared -Wl,-soname,libpri.so.1 -o $@ $(DYNAMIC_OBJS)
/sbin/ldconfig $(LDCONFIG_FLAGS) .
ln -sf libpri.so.1 libpri.so
clean:
rm -f *.o *.so *.lo *.so.$(SONAME)
rm -f testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
rm -f *.o *.so *.lo *.so.1 *.so.1.0
rm -f testpri testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
rm -f pritest pridump
rm -f .*.d
rm -f .depend
.PHONY:
depend: .depend
FORCE:
ifneq ($(wildcard .*.d),)
include .*.d
endif
.depend:
./mkdep ${CFLAGS} `ls *.c`

7
README
View File

@@ -1,4 +1,4 @@
libpri: An implementation of Primary Rate ISDN
libpri: An implementation of Primate Rate ISDN
Written by Mark Spencer <markster@digium.com>
@@ -16,11 +16,6 @@ libpri is distributed under the terms of the GNU General Public License,
which permit its use and linking with other GPL'd software only.
The GNU GPL is included in the file LICENSE in this directory.
As a special exception, libpri may also be linked to the OpenH323
library, so long as the entirity of the derivative work (as defined
within the GPL) is licensed either under the MPL of the OpenH323 license
or the GPL of libpri.
If you wish to use libpri in an application for which the GPL is not
appropriate (e.g. a proprietary embedded system), licenses for libpri
under more flexible terms can be readily obtained through Digium, Inc.

4
TODO
View File

@@ -1,8 +1,10 @@
General:
-- D-Channel Backup
-- Test against 4e
Q.921:
-- Support unnumbered information frames
-- Get TEI codes working for BRI interfaces
Q.931:
-- Locking Shift IE
-- Implement the 11 missing Q.931 timers

257
asn1.h
View File

@@ -1,257 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief ASN.1 definitions and prototypes
*
* \details
* This file contains all ASN.1 primitive data structures and
* definitions needed for ROSE component encoding and decoding.
*
* ROSE - Remote Operations Service Element
* ASN.1 - Abstract Syntax Notation 1
* APDU - Application Protocol Data Unit
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#ifndef _LIBPRI_ASN1_H
#define _LIBPRI_ASN1_H
#include <string.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ------------------------------------------------------------------- */
/*! ASN.1 Identifier Octet - Tag class bits */
#define ASN1_CLASS_MASK 0xc0
#define ASN1_CLASS_UNIVERSAL 0x00 /*!< Universal primitive data types */
#define ASN1_CLASS_APPLICATION 0x40 /*!< Application wide data tag */
#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /*!< Context specifc data tag */
#define ASN1_CLASS_PRIVATE 0xc0 /*!< Private organization data tag */
/*! ASN.1 Identifier Octet - Primitive/Constructor bit */
#define ASN1_PC_MASK 0x20
#define ASN1_PC_PRIMITIVE 0x00
#define ASN1_PC_CONSTRUCTED 0x20
/*! ASN.1 Identifier Octet - Universal data types */
#define ASN1_TYPE_MASK 0x1f
#define ASN1_TYPE_INDEF_TERM 0x00 /* 0 */
#define ASN1_TYPE_BOOLEAN 0x01 /* 1 */
#define ASN1_TYPE_INTEGER 0x02 /* 2 */
#define ASN1_TYPE_BIT_STRING 0x03 /* 3 */
#define ASN1_TYPE_OCTET_STRING 0x04 /* 4 */
#define ASN1_TYPE_NULL 0x05 /* 5 */
#define ASN1_TYPE_OBJECT_IDENTIFIER 0x06 /* 6 */
#define ASN1_TYPE_OBJECT_DESCRIPTOR 0x07 /* 7 */
#define ASN1_TYPE_EXTERN 0x08 /* 8 */
#define ASN1_TYPE_REAL 0x09 /* 9 */
#define ASN1_TYPE_ENUMERATED 0x0a /* 10 */
#define ASN1_TYPE_EMBEDDED_PDV 0x0b /* 11 */
#define ASN1_TYPE_UTF8_STRING 0x0c /* 12 */
#define ASN1_TYPE_RELATIVE_OID 0x0d /* 13 */
/* 0x0e & 0x0f are reserved for future ASN.1 editions */
#define ASN1_TYPE_SEQUENCE 0x10 /* 16 */
#define ASN1_TYPE_SET 0x11 /* 17 */
#define ASN1_TYPE_NUMERIC_STRING 0x12 /* 18 */
#define ASN1_TYPE_PRINTABLE_STRING 0x13 /* 19 */
#define ASN1_TYPE_TELETEX_STRING 0x14 /* 20 */
#define ASN1_TYPE_VIDEOTEX_STRING 0x15 /* 21 */
#define ASN1_TYPE_IA5_STRING 0x16 /* 22 */
#define ASN1_TYPE_UTC_TIME 0x17 /* 23 */
#define ASN1_TYPE_GENERALIZED_TIME 0x18 /* 24 */
#define ASN1_TYPE_GRAPHIC_STRING 0x19 /* 25 */
#define ASN1_TYPE_VISIBLE_STRING 0x1a /* 26 */
#define ASN1_TYPE_ISO646_STRING 0x1a /* 26 */
#define ASN1_TYPE_GENERAL_STRING 0x1b /* 27 */
#define ASN1_TYPE_UNIVERSAL_STRING 0x1c /* 28 */
#define ASN1_TYPE_CHAR_STRING 0x1d /* 29 */
#define ASN1_TYPE_BMP_STRING 0x1e /* 30 */
#define ASN1_TYPE_EXTENSION 0x1f /* 31 */
#define ASN1_TAG_SEQUENCE (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SEQUENCE)
#define ASN1_TAG_SET (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SET)
#define ASN1_INDEF_TERM (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_INDEF_TERM)
#define ASN1_INDEF_TERM_LEN 2
struct asn1_oid {
/*! \brief Number of subidentifier values in OID list */
u_int16_t num_values;
/*!
* \brief OID subidentifier value list
* \note The first value is really the first two OID subidentifiers.
* They are compressed using this formula:
* First_Value = (First_Subidentifier * 40) + Second_Subidentifier
*/
u_int16_t value[10];
};
#define ASN1_CALL(new_pos, do_it) \
do \
{ \
(new_pos) = (do_it); \
if (!(new_pos)) { \
return NULL; \
} \
} while (0)
/*! \brief Determine the ending position of the set or sequence to verify the length. */
#define ASN1_END_SETUP(component_end, offset, length, pos, end) \
do { \
if ((length) < 0) { \
(offset) = ASN1_INDEF_TERM_LEN; \
(component_end) = (end); \
} else { \
(offset) = 0; \
(component_end) = (pos) + (length); \
} \
} while (0)
/*! \brief Account for the indefinite length terminator of the set or sequence. */
#define ASN1_END_FIXUP(ctrl, pos, offset, component_end, end) \
do { \
if (offset) { \
ASN1_CALL((pos), asn1_dec_indef_end_fixup((ctrl), (pos), (end))); \
} else if ((pos) != (component_end)) { \
if ((ctrl)->debug & PRI_DEBUG_APDU) { \
pri_message((ctrl), \
" Skipping unused constructed component octets!\n"); \
} \
(pos) = (component_end); \
} \
} while (0)
#define ASN1_DID_NOT_EXPECT_TAG(ctrl, tag) \
do { \
if ((ctrl)->debug & PRI_DEBUG_APDU) { \
pri_message((ctrl), " Did not expect: %s\n", asn1_tag2str(tag)); \
} \
} while (0)
#define ASN1_CHECK_TAG(ctrl, actual_tag, match_tag, expected_tag) \
do { \
if ((match_tag) != (expected_tag)) { \
ASN1_DID_NOT_EXPECT_TAG((ctrl), (actual_tag)); \
return NULL; \
} \
} while (0)
const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end,
unsigned *tag);
const unsigned char *asn1_dec_length(const unsigned char *len_pos,
const unsigned char *end, int *length);
const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos,
const unsigned char *end);
const unsigned char *asn1_dec_boolean(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, int32_t *value);
const unsigned char *asn1_dec_int(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, int32_t *value);
const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end);
const unsigned char *asn1_dec_oid(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, struct asn1_oid *oid);
const unsigned char *asn1_dec_string_bin(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
unsigned char *str, size_t *str_len);
const unsigned char *asn1_dec_string_max(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
unsigned char *str, size_t *str_len);
const char *asn1_tag2str(unsigned tag);
void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1,
const unsigned char *end);
#define ASN1_LEN_FORM_SHORT 1 /*!< Hint that the final length will be less than 128 octets */
#define ASN1_LEN_FORM_LONG_U8 2 /*!< Hint that the final length will be less than 256 octets */
#define ASN1_LEN_FORM_LONG_U16 3 /*!< Hint that the final length will be less than 65536 octets */
#define ASN1_LEN_INIT(len_pos, end, form_hint) \
do { \
if ((end) < (len_pos) + (form_hint)) { \
return NULL; \
} \
*(len_pos) = (form_hint); \
(len_pos) += (form_hint); \
} while (0)
#define ASN1_LEN_FIXUP(len_pos, component_end, end) \
ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end)))
/*! \brief Use to begin encoding explicit tags, SET, and SEQUENCE constructed groupings. */
#define ASN1_CONSTRUCTED_BEGIN(len_pos_save, pos, end, tag) \
do { \
if ((end) < (pos) + (1 + ASN1_LEN_FORM_SHORT)) { \
return NULL; \
} \
*(pos)++ = (tag) | ASN1_PC_CONSTRUCTED; \
(len_pos_save) = (pos); \
*(pos) = ASN1_LEN_FORM_SHORT; \
(pos) += ASN1_LEN_FORM_SHORT; \
} while (0)
/*! \brief Use to end encoding explicit tags, SET, and SEQUENCE constructed groupings. */
#define ASN1_CONSTRUCTED_END(len_pos, component_end, end) \
ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end)))
#define ASN1_ENC_ERROR(ctrl, msg) \
pri_error((ctrl), "%s error: %s\n", __FUNCTION__, (msg))
unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end,
size_t str_len);
unsigned char *asn1_enc_length_fixup(unsigned char *len_pos,
unsigned char *component_end, unsigned char *end);
unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag,
int32_t value);
unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag,
int32_t value);
unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag);
unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag,
const struct asn1_oid *oid);
unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag,
const unsigned char *str, size_t str_len);
unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag,
const unsigned char *str, size_t max_len);
/* ------------------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* _LIBPRI_ASN1_H */
/* ------------------------------------------------------------------- */
/* end asn1.h */

File diff suppressed because it is too large Load Diff

View File

@@ -1,79 +0,0 @@
#!/bin/sh
if [ -f ${1}/.version ]; then
cat ${1}/.version
elif [ -d .svn ]; then
PARTS=`LANG=C svn info ${1} | ${GREP} URL | ${AWK} '{print $2;}' | sed -e 's:^.*/svn/libpri/::' | sed -e 's:/: :g'`
BRANCH=0
TEAM=0
TAG=0
REV=`svnversion -c ${1} | cut -d: -f2`
INTEGRATED=`LANG=C svn pg automerge-propname ${1}`
if [ -z "${INTEGRATED}" ] ; then
INTEGRATED=svnmerge-integrated
fi
BASE=`LANG=C svn pg ${INTEGRATED} ${1} | cut -d: -f1`
if [ "${PARTS}" = "trunk" ] ; then
echo SVN-trunk-r${REV}
exit 0
fi
for PART in $PARTS ; do
if [ ${TAG} != 0 ] ; then
if [ "${PART}" = "autotag_for_be" ] ; then
continue
fi
if [ "${PART}" = "autotag_for_sx00i" ] ; then
continue
fi
RESULT="${PART}"
break
fi
if [ ${BRANCH} != 0 ] ; then
if [ -z "${RESULT}" ] ; then
RESULT="${PART}"
else
RESULT="${RESULT}-${PART}"
fi
break
fi
if [ ${TEAM} != 0 ] ; then
if [ -z "${RESULT}" ] ; then
RESULT="${PART}"
else
RESULT="${RESULT}-${PART}"
fi
continue
fi
if [ "${PART}" = "branches" ] ; then
BRANCH=1
RESULT="branch"
continue
fi
if [ "${PART}" = "tags" ] ; then
TAG=1
continue
fi
if [ "${PART}" = "team" ] ; then
TEAM=1
continue
fi
done
if [ ${TAG} != 0 ] ; then
echo ${RESULT}
else
echo SVN-${RESULT}-r${REV}${BASE:+-${BASE}}
fi
else
echo "UNKNOWN__and_probably_unsupported"
fi

View File

@@ -1,24 +0,0 @@
#!/bin/sh
if [ ! -f ../.flavor ]; then
EXTRA=""
else
aadkver=`cat ../.version`
aadkflavor=`cat ../.flavor`
EXTRA=" (${aadkflavor} ${aadkver})"
fi
cat << END
/*
* version.c
* Automatically generated
*/
#include "libpri.h"
static const char pri_version[] = "${PRIVERSION}${EXTRA}";
const char *pri_get_version(void)
{
return pri_version;
}
END

View File

@@ -1,10 +0,0 @@
#ifndef __COMPAT_H
#define __COMPAT_H
#ifdef SOLARIS
typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;
#endif
#endif

View File

@@ -1,36 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Compiler-specific macros and other items
*
* Copyright (C) 2005, Digium, Inc.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#ifndef _ASTERISK_COMPILER_H
#define _ASTERISK_COMPILER_H
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
#define __builtin_expect(exp, c) (exp)
#endif
#endif /* _ASTERISK_COMPILER_H */

View File

@@ -1,47 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
*
* Copyright (C) 2005, Digium, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "compiler.h"
#include "libpri.h"
#include "pri_internal.h"
void libpri_copy_string(char *dst, const char *src, size_t size)
{
while (*src && size) {
*dst++ = *src++;
size--;
}
if (__builtin_expect(!size, 0))
dst--;
*dst = '\0';
}

1102
libpri.h

File diff suppressed because it is too large Load Diff

113
mkdep Executable file
View File

@@ -0,0 +1,113 @@
#!/bin/sh -
#
# $OpenBSD: mkdep.gcc.sh,v 1.8 1998/09/02 06:40:07 deraadt Exp $
# $NetBSD: mkdep.gcc.sh,v 1.9 1994/12/23 07:34:59 jtc Exp $
#
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)mkdep.gcc.sh 8.1 (Berkeley) 6/6/93
#
D=.depend # default dependency file is .depend
append=0
pflag=
while :
do case "$1" in
# -a appends to the depend file
-a)
append=1
shift ;;
# -f allows you to select a makefile name
-f)
D=$2
shift; shift ;;
# the -p flag produces "program: program.c" style dependencies
# so .o's don't get produced
-p)
pflag=p
shift ;;
*)
break ;;
esac
done
if [ $# = 0 ] ; then
echo 'usage: mkdep [-p] [-f depend_file] [cc_flags] file ...'
exit 1
fi
DTMP=/tmp/mkdep$$
TMP=$DTMP/mkdep
um=`umask`
umask 022
if ! mkdir $DTMP ; then
echo failed to create tmp dir $DTMP
exit 1
fi
umask $um
trap 'rm -rf $DTMP ; trap 2 ; kill -2 $$' 1 2 3 13 15
if [ x$pflag = x ]; then
${CC:-cc} -M "$@" 2>/dev/null | sed -e 's; \./; ;g' > $TMP
else
${CC:-cc} -M "$@" 2>/dev/null | sed -e 's;\.o :; :;' -e 's; \./; ;g' > $TMP
fi
if [ $? != 0 ]; then
echo 'mkdep: compile failed.'
rm -rf $DTMP
exit 1
fi
if [ $append = 1 ]; then
cat $TMP >> $D
if [ $? != 0 ]; then
echo 'mkdep: append failed.'
rm -rf $DTMP
exit 1
fi
else
mv $TMP $D
if [ $? != 0 ]; then
echo 'mkdep: rename failed.'
rm -rf $DTMP
exit 1
fi
fi
rm -rf $DTMP
exit 0

1342
pri.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,212 +0,0 @@
/*
This file contains all data structures and definitions associated
with facility message usage and the ROSE components included
within those messages.
by Matthew Fredrickson <creslin@digium.com>
Copyright (C) Digium, Inc. 2004-2005
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#ifndef _PRI_FACILITY_H
#define _PRI_FACILITY_H
#include "pri_q931.h"
/* Forward declare some structs */
struct fac_extension_header;
struct rose_msg_invoke;
struct rose_msg_result;
struct rose_msg_error;
struct rose_msg_reject;
/* Protocol Profile field */
#define Q932_PROTOCOL_MASK 0x1F
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
#define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */
#define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */
#define Q932_PROTOCOL_GAT 0x16
#define Q932_PROTOCOL_EXTENSIONS 0x1F
/* Q.952 Divert cause */
#define Q952_DIVERT_REASON_UNKNOWN 0x00
#define Q952_DIVERT_REASON_CFU 0x01
#define Q952_DIVERT_REASON_CFB 0x02
#define Q952_DIVERT_REASON_CFNR 0x03
#define Q952_DIVERT_REASON_CD 0x04
#define Q952_DIVERT_REASON_IMMEDIATE 0x05
/* Q.SIG Divert cause. Listed in ECMA-174 */
#define QSIG_DIVERT_REASON_UNKNOWN 0x00 /* Call forward unknown reason */
#define QSIG_DIVERT_REASON_CFU 0x01 /* Call Forward Unconditional (other reason) */
#define QSIG_DIVERT_REASON_CFB 0x02 /* Call Forward Busy */
#define QSIG_DIVERT_REASON_CFNR 0x03 /* Call Forward No Reply */
/* Q.932 Type of number */
#define Q932_TON_UNKNOWN 0x00
#define Q932_TON_INTERNATIONAL 0x01
#define Q932_TON_NATIONAL 0x02
#define Q932_TON_NET_SPECIFIC 0x03
#define Q932_TON_SUBSCRIBER 0x04
#define Q932_TON_ABBREVIATED 0x06
/* Q.SIG Subscription Option. Listed in ECMA-174 */
#define QSIG_NO_NOTIFICATION 0x00
#define QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR 0x01
#define QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR 0x02
/*! Reasons an APDU callback is called. */
enum APDU_CALLBACK_REASON {
/*!
* \brief Send setup error. Abort and cleanup.
* \note The message may or may not actually get sent.
* \note The callback cannot generate an event subcmd.
* \note The callback should not send messages. Out of order messages will result.
*/
APDU_CALLBACK_REASON_ERROR,
/*!
* \brief Abort and cleanup.
* \note The APDU queue is being destroyed.
* \note The callback cannot generate an event subcmd.
* \note The callback cannot send messages as the call is likely being destroyed.
*/
APDU_CALLBACK_REASON_CLEANUP,
/*!
* \brief Timeout waiting for responses to the message.
* \note The callback can generate an event subcmd.
* \note The callback can send messages.
*/
APDU_CALLBACK_REASON_TIMEOUT,
/*!
* \brief Received a facility response message.
* \note The callback can generate an event subcmd.
* \note The callback can send messages.
*/
APDU_CALLBACK_REASON_MSG_RESULT,
/*!
* \brief Received a facility error message.
* \note The callback can generate an event subcmd.
* \note The callback can send messages.
*/
APDU_CALLBACK_REASON_MSG_ERROR,
/*!
* \brief Received a facility reject message.
* \note The callback can generate an event subcmd.
* \note The callback can send messages.
*/
APDU_CALLBACK_REASON_MSG_REJECT,
};
union apdu_msg_data {
const struct rose_msg_result *result;
const struct rose_msg_error *error;
const struct rose_msg_reject *reject;
};
union apdu_callback_param {
void *ptr;
long value;
char pad[8];
};
struct apdu_callback_data {
/*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
int invoke_id;
/*!
* \brief Time to wait for responses to APDU in ms.
* \note Set to 0 if send the message only.
* \note Set to less than 0 for PRI_TIMER_T_RESPONSE time.
*/
int timeout_time;
/*!
* \brief APDU callback function.
*
* \param reason Reason callback is called.
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param apdu APDU queued entry. Do not change!
* \param msg APDU response message data. (NULL if was not the reason called.)
*
* \note
* A callback must be supplied if the sender cares about any APDU_CALLBACK_REASON.
*
* \return TRUE if no more responses are expected.
*/
int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg);
/*! \brief Sender data for the callback function to identify the particular APDU. */
union apdu_callback_param user;
};
struct apdu_event {
/*! Linked list pointer */
struct apdu_event *next;
/*! TRUE if this APDU has been sent. */
int sent;
/*! What message to send the ADPU in */
int message;
/*! Sender supplied information to handle APDU response messages. */
struct apdu_callback_data response;
/*! Q.931 call leg. (Needed for the APDU timeout.) */
struct q931_call *call;
/*! Response timeout timer. */
int timer;
/*! Length of ADPU */
int apdu_len;
/*! ADPU to send */
unsigned char apdu[255];
};
/* Queues an MWI apdu on a the given call */
int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
/* starts a 2BCT */
int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
int send_reroute_request(struct pri *ctrl, q931_call *call, const struct q931_party_id *caller, const struct q931_party_redirecting *deflection, int subscription_option);
/* starts a QSIG Path Replacement */
int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int send_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);
int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response);
void pri_call_apdu_queue_cleanup(q931_call *call);
void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed);
/* Adds the "standard" APDUs to a call */
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1, const unsigned char *end);
void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_invoke *invoke);
void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_result *result);
void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
#endif /* _PRI_FACILITY_H */

View File

@@ -1,47 +1,31 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#ifndef _PRI_INTERNAL_H
#define _PRI_INTERNAL_H
#include <stddef.h>
#include <sys/time.h>
#include "pri_q921.h"
#include "pri_q931.h"
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
#define DBGHEAD __FILE__ ":%d %s: "
#define DBGINFO __LINE__,__PRETTY_FUNCTION__
/* Forward declare some structs */
struct apdu_event;
struct pri_sched {
struct timeval when;
@@ -49,28 +33,15 @@ struct pri_sched {
void *data;
};
/*! Maximum number of scheduled events active at the same time. */
struct q921_frame;
enum q931_state;
enum q931_mode;
/* No more than 128 scheduled events */
#define MAX_SCHED 128
/*! Maximum number of facility ie's to handle per incoming message. */
#define MAX_FACILITY_IES 8
/*! Accumulated pri_message() line until a '\n' is seen on the end. */
struct pri_msg_line {
/*! Accumulated buffer used. */
unsigned length;
/*! Accumulated pri_message() contents. */
char str[2048];
};
/*! \brief D channel controller structure */
struct pri {
int fd; /* File descriptor for D-Channel */
pri_io_cb read_func; /* Read data callback */
pri_io_cb write_func; /* Write data callback */
void *userdata;
/*! Accumulated pri_message() line. (Valid in master record only) */
struct pri_msg_line *msg_line;
struct pri *subchannel; /* Sub-channel if appropriate */
struct pri *master; /* Master channel if appropriate */
struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
@@ -84,53 +55,32 @@ struct pri {
int sapi;
int tei;
int protodisc;
unsigned int bri:1;
unsigned int acceptinbanddisconnect:1; /* Should we allow inband progress after DISCONNECT? */
unsigned int sendfacility:1;
unsigned int overlapdial:1;/* TRUE if we do overlap dialing */
unsigned int chan_mapping_logical:1;/* TRUE if do not skip channel 16 (Q.SIG) */
unsigned int service_message_support:1;/* TRUE if upper layer supports SERVICE messages */
unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
unsigned int hangup_fix_enabled:1;/* TRUE if should follow Q.931 Section 5.3.2 instead of blindly sending RELEASE_COMPLETE for certain causes */
/* MDL variables */
int mdl_error;
int mdl_error_state;
int mdl_timer;
int mdl_free_me;
/* Q.921 State */
int q921_state;
int RC;
int peer_rx_busy:1;
int own_rx_busy:1;
int acknowledge_pending:1;
int reject_exception:1;
int window; /* Max window size */
int windowlen; /* Fullness of window */
int v_s; /* Next N(S) for transmission */
int v_a; /* Last acknowledged frame */
int v_r; /* Next frame expected to be received */
int v_na; /* What we've told our peer we've acknowledged */
int solicitfbit; /* Have we sent an I or S frame with the F-bit set? */
int retrans; /* Retransmissions */
int sentrej; /* Are we in reject state */
int cref; /* Next call reference value */
int l3initiated;
int busy; /* Peer is busy */
/* Various timers */
int sabme_timer; /* SABME retransmit */
int t203_timer; /* Max idle time */
int t202_timer;
int n202_counter;
int ri;
int t200_timer; /* T-200 retransmission timer */
/* All ISDN Timer values */
int timers[PRI_MAX_TIMERS];
/* Used by scheduler */
struct timeval tv;
int schedev;
pri_event ev; /* Static event thingy */
/*! Subcommands for static event thingy. */
struct pri_subcommands subcmds;
/* Q.921 Re-transmission queue */
struct q921_frame *txqueue;
@@ -139,12 +89,8 @@ struct pri {
q931_call **callpool;
q931_call *localpool;
/*!
* \brief Q.931 Dummy call reference call associated with this TEI.
* \note If present then this call is allocated as part of the
* D channel control structure.
*/
q931_call *dummy_call;
/* do we do overlap dialing */
int overlapdial;
#ifdef LIBPRI_COUNTERS
/* q921/q931 packet counters */
@@ -153,392 +99,26 @@ struct pri {
unsigned int q931_txcount;
unsigned int q931_rxcount;
#endif
short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */
/*! For delayed processing of facility ie's. */
struct {
/*! Array of facility ie locations in the current received message. */
q931_ie *ie[MAX_FACILITY_IES];
/*! Codeset facility ie found within. */
unsigned char codeset[MAX_FACILITY_IES];
/*! Number of facility ie's in the array from the current received message. */
unsigned char count;
} facility;
};
/*! \brief Maximum name length plus null terminator (From ECMA-164) */
#define PRI_MAX_NAME_LEN (50 + 1)
/*! \brief Q.SIG name information. */
struct q931_party_name {
/*! \brief TRUE if name data is valid */
unsigned char valid;
/*!
* \brief Q.931 presentation-indicator encoded field
* \note Must tollerate the Q.931 screening-indicator field values being present.
*/
unsigned char presentation;
/*!
* \brief Character set the name is using.
* \details
* unknown(0),
* iso8859-1(1),
* enum-value-withdrawn-by-ITU-T(2)
* iso8859-2(3),
* iso8859-3(4),
* iso8859-4(5),
* iso8859-5(6),
* iso8859-7(7),
* iso10646-BmpString(8),
* iso10646-utf-8String(9)
*/
unsigned char char_set;
/*! \brief Name data with null terminator. */
char str[PRI_MAX_NAME_LEN];
};
/*! \brief Maximum phone number (address) length plus null terminator */
#define PRI_MAX_NUMBER_LEN (31 + 1)
struct q931_party_number {
/*! \brief TRUE if number data is valid */
unsigned char valid;
/*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
unsigned char presentation;
/*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
unsigned char plan;
/*! \brief Number data with terminator. */
char str[PRI_MAX_NUMBER_LEN];
};
/*! \brief Maximum subaddress length plus null terminator */
#define PRI_MAX_SUBADDRESS_LEN (20 + 1)
struct q931_party_subaddress {
/*! \brief TRUE if the subaddress information is valid/present */
unsigned char valid;
/*!
* \brief Subaddress type.
* \details
* nsap(0),
* user_specified(2)
*/
unsigned char type;
/*!
* \brief TRUE if odd number of address signals
* \note The odd/even indicator is used when the type of subaddress is
* user_specified and the coding is BCD.
*/
unsigned char odd_even_indicator;
/*! \brief Length of the subaddress data */
unsigned char length;
/*!
* \brief Subaddress data with null terminator.
* \note The null terminator is a convenience only since the data could be
* BCD/binary and thus have a null byte as part of the contents.
*/
unsigned char data[PRI_MAX_SUBADDRESS_LEN];
};
struct q931_party_address {
/*! \brief Subscriber phone number */
struct q931_party_number number;
/*! \brief Subscriber subaddress */
struct q931_party_subaddress subaddress;
};
/*! \brief Information needed to identify an endpoint in a call. */
struct q931_party_id {
/*! \brief Subscriber name */
struct q931_party_name name;
/*! \brief Subscriber phone number */
struct q931_party_number number;
/*! \brief Subscriber subaddress */
struct q931_party_subaddress subaddress;
};
enum Q931_REDIRECTING_STATE {
/*!
* \details
* CDO-Idle/CDF-Inv-Idle
*/
Q931_REDIRECTING_STATE_IDLE,
/*!
* \details
* CDF-Inv-Wait - A DivLeg2 has been received and
* we are waiting for valid presentation restriction information to send.
*/
Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3,
/*!
* \details
* CDO-Divert - A DivLeg1 has been received and
* we are waiting for the presentation restriction information to come in.
*/
Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3,
};
/*!
* \brief Do not increment above this count.
* \details
* It is not our responsibility to enforce the maximum number of redirects.
* However, we cannot allow an increment past this number without breaking things.
* Besides, more than 255 redirects is probably not a good thing.
*/
#define PRI_MAX_REDIRECTS 0xFF
/*! \brief Redirecting information struct */
struct q931_party_redirecting {
enum Q931_REDIRECTING_STATE state;
/*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
struct q931_party_id from;
/*! \brief Call is redirecting to a new party (Sent to the caller) */
struct q931_party_id to;
/*! Originally called party (in cases of multiple redirects) */
struct q931_party_id orig_called;
/*!
* \brief Number of times the call was redirected
* \note The call is being redirected if the count is non-zero.
*/
unsigned char count;
/*! Original reason for redirect (in cases of multiple redirects) */
unsigned char orig_reason;
/*! \brief Redirection reasons */
unsigned char reason;
};
/*! \brief New call setup parameter structure */
struct pri_sr {
int transmode;
int channel;
int exclusive;
int nonisdn;
struct q931_party_redirecting redirecting;
struct q931_party_id caller;
struct q931_party_address called;
char *caller;
int callerplan;
char *callername;
int callerpres;
char *called;
int calledplan;
int userl1;
int numcomplete;
int cis_call;
int cis_auto_disconnect;
const char *useruserinfo;
const char *keypad_digits;
int transferable;
int reversecharge;
};
/* Internal switch types */
#define PRI_SWITCH_GR303_EOC_PATH 19
#define PRI_SWITCH_GR303_TMC_SWITCHING 20
#define Q931_MAX_TEI 8
/*! \brief Incoming call transfer states. */
enum INCOMING_CT_STATE {
/*!
* \details
* Incoming call transfer is not active.
*/
INCOMING_CT_STATE_IDLE,
/*!
* \details
* We have seen an incoming CallTransferComplete(alerting)
* so we are waiting for the expected CallTransferActive
* before updating the connected line about the remote party id.
*/
INCOMING_CT_STATE_EXPECT_CT_ACTIVE,
/*!
* \details
* A call transfer message came in that updated the remote party id
* that we need to post a connected line update.
*/
INCOMING_CT_STATE_POST_CONNECTED_LINE
};
/*! Call hold supplementary states. */
enum Q931_HOLD_STATE {
/*! \brief No call hold activity. */
Q931_HOLD_STATE_IDLE,
/*! \brief Request made to hold call. */
Q931_HOLD_STATE_HOLD_REQ,
/*! \brief Request received to hold call. */
Q931_HOLD_STATE_HOLD_IND,
/*! \brief Call is held. */
Q931_HOLD_STATE_CALL_HELD,
/*! \brief Request made to retrieve call. */
Q931_HOLD_STATE_RETRIEVE_REQ,
/*! \brief Request received to retrieve call. */
Q931_HOLD_STATE_RETRIEVE_IND,
};
/* q931_call datastructure */
struct q931_call {
struct pri *pri; /* PRI */
int cr; /* Call Reference */
q931_call *next;
/* Slotmap specified (bitmap of channels 31/24-1) (Channel Identifier IE) (-1 means not specified) */
int slotmap;
/* An explicit channel (Channel Identifier IE) (-1 means not specified) */
int channelno;
/* An explicit DS1 (-1 means not specified) */
int ds1no;
/* Whether or not the ds1 is explicitly identified or implicit. If implicit
the bchan is on the same span as the current active dchan (NFAS) */
int ds1explicit;
/* Channel flags (0 means none retrieved) */
int chanflags;
int alive; /* Whether or not the call is alive */
int acked; /* Whether setup has been acked or not */
int sendhangupack; /* Whether or not to send a hangup ack */
int proc; /* Whether we've sent a call proceeding / alerting */
int ri; /* Restart Indicator (Restart Indicator IE) */
/* Bearer Capability */
int transcapability;
int transmoderate;
int transmultiple;
int userl1;
int userl2;
int userl3;
int rateadaption;
/*!
* \brief TRUE if the call is a Call Independent Signalling connection.
* \note The call has no B channel associated with it. (Just signalling)
*/
int cis_call;
/*! \brief TRUE if we will auto disconnect the cis_call we originated. */
int cis_auto_disconnect;
int progcode; /* Progress coding */
int progloc; /* Progress Location */
int progress; /* Progress indicator */
int progressmask; /* Progress Indicator bitmask */
int notify; /* Notification indicator. */
int causecode; /* Cause Coding */
int causeloc; /* Cause Location */
int cause; /* Cause of clearing */
enum Q931_CALL_STATE peercallstate; /* Call state of peer as reported */
enum Q931_CALL_STATE ourcallstate; /* Our call state */
enum Q931_CALL_STATE sugcallstate; /* Status call state */
int ani2; /* ANI II */
/*! Buffer for digits that come in KEYPAD_FACILITY */
char keypad_digits[32 + 1];
/*! Current dialed digits to be sent or just received. */
char overlap_digits[PRI_MAX_NUMBER_LEN];
/*!
* \brief Local party ID
* \details
* The Caller-ID and connected-line ID are just roles the local and remote party
* play while a call is being established. Which roll depends upon the direction
* of the call.
* Outgoing party info is to identify the local party to the other end.
* (Caller-ID for originated or connected-line for answered calls.)
* Incoming party info is to identify the remote party to us.
* (Caller-ID for answered or connected-line for originated calls.)
*/
struct q931_party_id local_id;
/*!
* \brief Remote party ID
* \details
* The Caller-ID and connected-line ID are just roles the local and remote party
* play while a call is being established. Which roll depends upon the direction
* of the call.
* Outgoing party info is to identify the local party to the other end.
* (Caller-ID for originated or connected-line for answered calls.)
* Incoming party info is to identify the remote party to us.
* (Caller-ID for answered or connected-line for originated calls.)
*/
struct q931_party_id remote_id;
/*!
* \brief Staging place for the Q.931 redirection number ie.
* \note
* The number could be the remote_id.number or redirecting.to.number
* depending upon the notification indicator.
*/
struct q931_party_number redirection_number;
/*!
* \brief Called party address.
* \note The called.number.str is the accumulated overlap dial digits
* and enbloc digits.
* \note The called.number.presentation value is not used.
*/
struct q931_party_address called;
int nonisdn;
int complete; /* no more digits coming */
int newcall; /* if the received message has a new call reference value */
int retranstimer; /* Timer for retransmitting DISC */
int t308_timedout; /* Whether t308 timed out once */
struct q931_party_redirecting redirecting;
/*! \brief Incoming call transfer state. */
enum INCOMING_CT_STATE incoming_ct_state;
/*! Call hold supplementary state. */
enum Q931_HOLD_STATE hold_state;
/*! Call hold event timer */
int hold_timer;
int deflection_in_progress; /*!< CallDeflection for NT PTMP in progress. */
/*! TRUE if the connected number ie was in the current received message. */
int connected_number_in_message;
/*! TRUE if the redirecting number ie was in the current received message. */
int redirecting_number_in_message;
int useruserprotocoldisc;
char useruserinfo[256];
long aoc_units; /* Advice of Charge Units */
struct apdu_event *apdus; /* APDU queue for call */
int transferable; /* RLT call is transferable */
unsigned int rlt_call_id; /* RLT call id */
/* Bridged call info */
q931_call *bridged_call; /* Pointer to other leg of bridged call (Used by Q.SIG when eliminating tromboned calls) */
int changestatus; /* SERVICE message changestatus */
int reversecharge; /* Reverse charging indication:
-1 - No reverse charging
1 - Reverse charging
0,2-7 - Reserved for future use */
int t303_timer;
int t303_expirycnt;
int hangupinitiated;
/*! \brief TRUE if we broadcast this call's SETUP message. */
int outboundbroadcast;
int performing_fake_clearing;
/*!
* \brief Master call controlling this call.
* \note Always valid. Master and normal calls point to self.
*/
struct q931_call *master_call;
/* These valid in master call only */
struct q931_call *subcalls[Q931_MAX_TEI];
int pri_winner;
};
/*! D channel control structure with associated dummy call reference record. */
struct d_ctrl_dummy {
/*! D channel control structure. Must be first in the structure. */
struct pri ctrl;
/*! Dummy call reference call record. */
struct q931_call dummy_call;
};
#define PRI_SWITCH_GR303_EOC_PATH 10
#define PRI_SWITCH_GR303_TMC_SWITCHING 11
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
@@ -548,187 +128,8 @@ extern void pri_schedule_del(struct pri *pri, int ev);
extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
void pri_message(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void pri_error(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
extern void pri_message(char *fmt, ...);
void libpri_copy_string(char *dst, const char *src, size_t size);
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
void __pri_free_tei(struct pri *p);
void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
void q931_party_name_init(struct q931_party_name *name);
void q931_party_number_init(struct q931_party_number *number);
void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
void q931_party_address_init(struct q931_party_address *address);
void q931_party_id_init(struct q931_party_id *id);
void q931_party_redirecting_init(struct q931_party_redirecting *redirecting);
static inline void q931_party_address_to_id(struct q931_party_id *id, struct q931_party_address *address)
{
id->number = address->number;
id->subaddress = address->subaddress;
}
int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right);
int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right);
int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right);
int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right);
void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name);
void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number);
void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress);
void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id);
void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting);
void pri_copy_party_name_to_q931(struct q931_party_name *q931_name, const struct pri_party_name *pri_name);
void pri_copy_party_number_to_q931(struct q931_party_number *q931_number, const struct pri_party_number *pri_number);
void pri_copy_party_subaddress_to_q931(struct q931_party_subaddress *q931_subaddress, const struct pri_party_subaddress *pri_subaddress);
void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_party_id *pri_id);
void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
int q931_party_id_presentation(const struct q931_party_id *id);
const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
const char *msg2str(int msg);
int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type);
struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
/*!
* \brief Get the master PRI control structure.
*
* \param ctrl D channel controller.
*
* \return Master PRI control structure.
*/
static inline struct pri *PRI_MASTER(struct pri *ctrl)
{
while (ctrl->master) {
ctrl = ctrl->master;
}
return ctrl;
}
/*!
* \brief Determine if layer 2 is in BRI NT PTMP mode.
*
* \param ctrl D channel controller.
*
* \retval TRUE if in BRI NT PTMP mode.
* \retval FALSE otherwise.
*/
static inline int BRI_NT_PTMP(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->bri && my_ctrl->localtype == PRI_NETWORK
&& my_ctrl->tei == Q921_TEI_GROUP;
}
/*!
* \brief Determine if layer 2 is in BRI TE PTMP mode.
*
* \param ctrl D channel controller.
*
* \retval TRUE if in BRI TE PTMP mode.
* \retval FALSE otherwise.
*/
static inline int BRI_TE_PTMP(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->bri && my_ctrl->localtype == PRI_CPE
&& my_ctrl->tei == Q921_TEI_GROUP;
}
/*!
* \brief Determine if layer 2 is in NT mode.
*
* \param ctrl D channel controller.
*
* \retval TRUE if in NT mode.
* \retval FALSE otherwise.
*/
static inline int NT_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->localtype == PRI_NETWORK;
}
/*!
* \brief Determine if layer 2 is in TE mode.
*
* \param ctrl D channel controller.
*
* \retval TRUE if in TE mode.
* \retval FALSE otherwise.
*/
static inline int TE_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->localtype == PRI_CPE;
}
/*!
* \brief Determine if layer 2 is in PTP mode.
*
* \param ctrl D channel controller.
*
* \retval TRUE if in PTP mode.
* \retval FALSE otherwise.
*/
static inline int PTP_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->tei == Q921_TEI_PRI;
}
/*!
* \brief Determine if layer 2 is in PTMP mode.
*
* \param ctrl D channel controller.
*
* \retval TRUE if in PTMP mode.
* \retval FALSE otherwise.
*/
static inline int PTMP_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->tei == Q921_TEI_GROUP;
}
#define Q931_DUMMY_CALL_REFERENCE -1
#define Q931_CALL_REFERENCE_FLAG 0x8000 /* Identify which end allocted the CR. */
/*!
* \brief Deterimine if the given call control pointer is a dummy call.
*
* \retval TRUE if given call is a dummy call.
* \retval FALSE otherwise.
*/
static inline int q931_is_dummy_call(const q931_call *call)
{
return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
}
extern void pri_error(char *fmt, ...);
#endif

View File

@@ -1,30 +1,25 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#ifndef _PRI_Q921_H
@@ -44,6 +39,9 @@
#define T_WAIT_MIN 2000
#define T_WAIT_MAX 10000
#define T_200 1000 /* 1 second between SABME's */
#define T_203 10000 /* 10 seconds with no packets max */
#define N_200 3 /* 3 retries */
#define Q921_FRAMETYPE_MASK 0x3
@@ -51,11 +49,10 @@
#define Q921_FRAMETYPE_I 0x0
#define Q921_FRAMETYPE_S 0x1
#define Q921_TEI_GROUP 127
#define Q921_TEI_PRI 0
#define Q921_TEI_GROUP 127
#define Q921_TEI_GR303_EOC_PATH 0
#define Q921_TEI_GR303_EOC_OPS 4
#define Q921_TEI_GR303_TMC_SWITCHING 0
#define Q921_TEI_GR303_TMC_SWITCHING 0
#define Q921_TEI_GR303_TMC_CALLPROC 0
#define Q921_SAPI_CALL_CTRL 0
@@ -69,14 +66,6 @@
#define Q921_SAPI_LAYER2_MANAGEMENT 63
#define Q921_TEI_IDENTITY_REQUEST 1
#define Q921_TEI_IDENTITY_ASSIGNED 2
#define Q921_TEI_IDENTITY_DENIED 3
#define Q921_TEI_IDENTITY_CHECK_REQUEST 4
#define Q921_TEI_IDENTITY_CHECK_RESPONSE 5
#define Q921_TEI_IDENTITY_REMOVE 6
#define Q921_TEI_IDENTITY_VERIFY 7
typedef struct q921_header {
#if __BYTE_ORDER == __BIG_ENDIAN
u_int8_t sapi:6; /* Service Access Point Indentifier (always 0 for PRI) (0) */
@@ -92,7 +81,7 @@ typedef struct q921_header {
u_int8_t tei:7; /* Terminal Endpoint Identifier (0) */
#endif
u_int8_t data[0]; /* Further data */
} __attribute__ ((packed)) q921_header;
} q921_header;
/* A Supervisory Format frame */
typedef struct q921_s {
@@ -112,7 +101,7 @@ typedef struct q921_s {
#endif
u_int8_t data[0]; /* Any further data */
u_int8_t fcs[2]; /* At least an FCS */
} __attribute__ ((packed)) q921_s;
} q921_s;
/* An Unnumbered Format frame */
typedef struct q921_u {
@@ -130,7 +119,7 @@ typedef struct q921_u {
#endif
u_int8_t data[0]; /* Any further data */
u_int8_t fcs[2]; /* At least an FCS */
} __attribute__ ((packed)) q921_u;
} q921_u;
/* An Information frame */
typedef struct q921_i {
@@ -166,41 +155,24 @@ typedef struct q921_frame {
} q921_frame;
#define Q921_INC(j) (j) = (((j) + 1) % 128)
#define Q921_DEC(j) (j) = (((j) - 1) % 128)
typedef enum q921_state {
/* All states except Q921_DOWN are defined in Q.921 SDL diagrams */
Q921_TEI_UNASSIGNED = 1,
Q921_ASSIGN_AWAITING_TEI = 2,
Q921_ESTABLISH_AWAITING_TEI = 3,
Q921_TEI_ASSIGNED = 4,
Q921_AWAITING_ESTABLISHMENT = 5,
Q921_AWAITING_RELEASE = 6,
Q921_MULTI_FRAME_ESTABLISHED = 7,
Q921_TIMER_RECOVERY = 8,
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
Q921_LINK_CONNECTION_ESTABLISHED,
Q921_AWAITING_ESTABLISH,
Q921_AWAITING_RELEASE
} q921_state;
static inline int Q921_ADD(int a, int b)
{
return (a + b) % 128;
}
/* Dumps a *known good* Q.921 packet */
extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx);
extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
/* Bring up the D-channel */
extern void q921_start(struct pri *pri);
extern void q921_start(struct pri *pri, int now);
//extern void q921_reset(struct pri *pri, int reset_iqueue);
extern void q921_reset(struct pri *pri);
extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
extern int q921_transmit_iframe(struct pri *pri, int tei, void *buf, int len, int cr);
extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
extern pri_event *q921_dchannel_up(struct pri *pri);
//extern pri_event *q921_dchannel_down(struct pri *pri);
extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
#endif

View File

@@ -1,35 +1,68 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#ifndef _PRI_Q931_H
#define _PRI_Q931_H
typedef enum q931_state {
/* User states */
U0_NULL_STATE,
U1_CALL_INITIATED,
U2_OVERLAP_SENDING,
U3_OUTGOING_CALL_PROCEEDING,
U4_CALL_DELIVERED,
U6_CALL_PRESENT,
U7_CALL_RECEIVED,
U8_CONNECT_REQUEST,
U9_INCOMING_CALL_PROCEEDING,
U10_ACTIVE,
U11_DISCONNECT_REQUEST,
U12_DISCONNECT_INDICATION,
U15_SUSPEND_REQUEST,
U17_RESUME_REQUEST,
U19_RELEASE_REQUEST,
U25_OVERLAP_RECEIVING,
/* Network states */
N0_NULL_STATE,
N1_CALL_INITIATED,
N2_OVERLAP_SENDING,
N3_OUTGOING_CALL_PROCEEDING,
N4_CALL_DELIVERED,
N6_CALL_PRESENT,
N7_CALL_RECEIVED,
N8_CONNECT_REQUEST,
N9_INCOMING_CALL_PROCEEDING,
N10_ACTIVE,
N11_DISCONNECT_REQUEST,
N12_DISCONNECT_INDICATION,
N15_SUSPEND_REQUEST,
N17_RESUME_REQUEST,
N19_RELEASE_REQUEST,
N22_CALL_ABORT,
N25_OVERLAP_RECEIVING
} q931_state;
typedef enum q931_mode {
UNKNOWN_MODE,
CIRCUIT_MODE,
@@ -41,14 +74,14 @@ typedef struct q931_h {
u_int8_t pd; /* Protocol Discriminator */
#if __BYTE_ORDER == __BIG_ENDIAN
u_int8_t x0:4;
u_int8_t crlen:4;/*!< Call reference length */
u_int8_t crlen:4;
#else
u_int8_t crlen:4;/*!< Call reference length */
u_int8_t crlen:4;
u_int8_t x0:4;
#endif
u_int8_t contents[0];
u_int8_t crv[3];/*!< Call reference value */
} __attribute__ ((packed)) q931_h;
u_int8_t crv[3];
} q931_h;
/* Message type header */
@@ -61,24 +94,20 @@ typedef struct q931_mh {
u_int8_t f:1;
#endif
u_int8_t data[0];
} __attribute__ ((packed)) q931_mh;
} q931_mh;
/* Information element format */
typedef struct q931_ie {
u_int8_t ie;
u_int8_t len;
u_int8_t data[0];
} __attribute__ ((packed)) q931_ie;
} q931_ie;
#define Q931_RES_HAVEEVENT (1 << 0)
#define Q931_RES_INERRROR (1 << 1)
#define Q931_PROTOCOL_DISCRIMINATOR 0x08
#define GR303_PROTOCOL_DISCRIMINATOR 0x4f
/* AT&T Maintenance Protocol Discriminator */
#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 0x03
/* National Maintenance Protocol Discriminator */
#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_2 0x43
/* Q.931 / National ISDN Message Types */
@@ -123,16 +152,8 @@ typedef struct q931_ie {
#define Q931_SUSPEND_REJECT 0x21
/* Maintenance messages (codeset 0 only) */
#define ATT_SERVICE 0x0f
#define ATT_SERVICE_ACKNOWLEDGE 0x07
#define NATIONAL_SERVICE 0x07
#define NATIONAL_SERVICE_ACKNOWLEDGE 0x0f
#define SERVICE_CHANGE_STATUS_INSERVICE 0
#define SERVICE_CHANGE_STATUS_LOOPBACK 1 /* not supported */
#define SERVICE_CHANGE_STATUS_OUTOFSERVICE 2
#define SERVICE_CHANGE_STATUS_REQCONTINUITYCHECK 3 /* not supported */
#define SERVICE_CHANGE_STATUS_SHUTDOWN 4 /* not supported */
#define NATIONAL_SERVICE 0x0f
#define NATIONAL_SERVICE_ACKNOWLEDGE 0x07
/* Special codeset 0 IE */
#define NATIONAL_CHANGE_STATUS 0x1
@@ -142,11 +163,10 @@ typedef struct q931_ie {
#define Q931_NON_LOCKING_SHIFT 0x98
#define Q931_BEARER_CAPABILITY 0x04
#define Q931_CAUSE 0x08
#define Q931_IE_CALL_STATE 0x14
#define Q931_CALL_STATE 0x14
#define Q931_CHANNEL_IDENT 0x18
#define Q931_PROGRESS_INDICATOR 0x1e
#define Q931_NETWORK_SPEC_FAC 0x20
#define Q931_CALLING_PARTY_CATEGORY (0x32 | Q931_CODESET(5))
#define Q931_INFORMATION_RATE 0x40
#define Q931_TRANSIT_DELAY 0x42
#define Q931_TRANS_DELAY_SELECT 0x43
@@ -175,9 +195,8 @@ typedef struct q931_ie {
#define Q931_IE_SEGMENTED_MSG 0x00
#define Q931_IE_CHANGE_STATUS 0x01
#define Q931_IE_ORIGINATING_LINE_INFO (0x01 | Q931_CODESET(6))
#define Q931_IE_CONNECTED_ADDR 0x0c
#define Q931_IE_CONNECTED_NUM 0x4c
#define Q931_IE_CONNECTED_SUBADDR 0x4d
#define Q931_IE_CONNECTED_ADDR 0x0C
#define Q931_IE_CONNECTED_NUM 0x4C
#define Q931_IE_CALL_IDENTITY 0x10
#define Q931_IE_FACILITY 0x1c
#define Q931_IE_ENDPOINT_ID 0x26
@@ -189,7 +208,6 @@ typedef struct q931_ie {
#define Q931_IE_INFO_REQUEST 0x32
#define Q931_IE_SIGNAL 0x34
#define Q931_IE_SWITCHHOOK 0x36
#define Q931_IE_GENERIC_DIGITS (0x37 | Q931_CODESET(6))
#define Q931_IE_FEATURE_ACTIVATE 0x38
#define Q931_IE_FEATURE_IND 0x39
#define Q931_IE_ORIGINAL_CALLED_NUMBER 0x73
@@ -200,264 +218,34 @@ typedef struct q931_ie {
#define Q931_IE_ESCAPE_FOR_EXT 0x7F
/*! Q.931 call states */
enum Q931_CALL_STATE {
/*!
* \details
* null state (U0):
* No call exists.
* \details
* null state (N0):
* No call exists.
*/
Q931_CALL_STATE_NULL = 0,
/*!
* \details
* call initiated (U1):
* This state exists for an outgoing call, when the user requests
* call establishment from the network.
* \details
* call initiated (N1):
* This state exists for an outgoing call when the network has received
* a call establishment request but has not yet responded.
*/
Q931_CALL_STATE_CALL_INITIATED = 1,
/*!
* \details
* overlap sending (U2):
* This state exists for an outgoing call when the user has
* received acknowledgement of the call establishment request which
* permits the user to send additional call information to the network
* in overlap mode.
* \details
* overlap sending (N2):
* This state exists for an outgoing call when the network has acknowledged
* the call establishment request and is prepared to receive additional
* call information (if any) in overlap mode.
*/
Q931_CALL_STATE_OVERLAP_SENDING = 2,
/*!
* \details
* outgoing call proceeding (U3):
* This state exists for an outgoing call when the user has
* received acknowledgement that the network has received all
* call information necessary to effect call establishment.
* \details
* outgoing call proceeding (N3):
* This state exists for an outgoing call when the network has sent
* acknowledgement that the network has received all call information
* necessary to effect call establishment.
*/
Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING = 3,
/*!
* \details
* call delivered (U4):
* This state exists for an outgoing call when the calling user has
* received an indication that remote user alerting has been initiated.
* \details
* call delivered (N4):
* This state exists for an outgoing call when the network has indicated
* that remote user alerting has been initiated.
*/
Q931_CALL_STATE_CALL_DELIVERED = 4,
/*!
* \details
* call present (U6):
* This state exists for an incoming call when the user has received a
* call establishment request but has not yet responded.
* \details
* call present (N6):
* This state exists for an incoming call when the network has sent a
* call establishment request but has not yet received a satisfactory
* response.
*/
Q931_CALL_STATE_CALL_PRESENT = 6,
/*!
* \details
* call received (U7):
* This state exists for an incoming call when the user has indicated
* alerting but has not yet answered.
* \details
* call received (N7):
* This state exists for an incoming call when the network has received
* an indication that the user is alerting but has not yet received an
* answer.
*/
Q931_CALL_STATE_CALL_RECEIVED = 7,
/*!
* \details
* connect request (U8):
* This state exists for an incoming call when the user has answered
* the call and is waiting to be awarded the call.
* \details
* connect request (N8):
* This state exists for an incoming call when the network has received
* an answer but the network has not yet awarded the call.
*/
Q931_CALL_STATE_CONNECT_REQUEST = 8,
/*!
* \details
* incoming call proceeding (U9):
* This state exists for an incoming call when the user has sent
* acknowledgement that the user has received all call information
* necessary to effect call establishment.
* \details
* incoming call proceeding (N9):
* This state exists for an incoming call when the network has received
* acknowledgement that the user has received all call information
* necessary to effect call establishment.
*/
Q931_CALL_STATE_INCOMING_CALL_PROCEEDING = 9,
/*!
* \details
* active (U10):
* This state exists for an incoming call when the user has received
* an acknowledgement from the network that the user has been awarded
* the call. This state exists for an outgoing call when the user has
* received an indication that the remote user has answered the call.
* \details
* active (N10):
* This state exists for an incoming call when the network has awarded
* the call to the called user. This state exists for an outgoing call
* when the network has indicated that the remote user has answered
* the call.
*/
Q931_CALL_STATE_ACTIVE = 10,
/*!
* \details
* disconnect request (U11):
* This state exists when the user has requested the network to clear
* the end-to-end connection (if any) and is waiting for a response.
* \details
* disconnect request (N11):
* This state exists when the network has received a request from the
* user to clear the end-to-end connection (if any).
*/
Q931_CALL_STATE_DISCONNECT_REQUEST = 11,
/*!
* \details
* disconnect indication (U12):
* This state exists when the user has received an invitation to
* disconnect because the network has disconnected the end-to-end
* connection (if any).
* \details
* disconnect indication (N12):
* This state exists when the network has disconnected the end-to-end
* connection (if any) and has sent an invitation to disconnect the
* user-network connection.
*/
Q931_CALL_STATE_DISCONNECT_INDICATION = 12,
/*!
* \details
* suspend request (U15):
* This state exists when the user has requested the network to suspend
* the call and is waiting for a response.
* \details
* suspend request (N15):
* This state exists when the network has received a request to suspend
* the call but has not yet responded.
*/
Q931_CALL_STATE_SUSPEND_REQUEST = 15,
/*!
* \details
* resume request (U17):
* This state exists when the user has requested the network to resume
* a previously suspended call and is waiting for a response.
* \details
* resume request (N17):
* This state exists when the network has received a request to resume
* a previously suspended call but has not yet responded.
*/
Q931_CALL_STATE_RESUME_REQUEST = 17,
/*!
* \details
* release request (U19):
* This state exists when the user has requested the network to release
* and is waiting for a response.
* \details
* release request (N19):
* This state exists when the network has requested the user to release
* and is waiting for a response.
*/
Q931_CALL_STATE_RELEASE_REQUEST = 19,
/*!
* \details
* call abort (N22):
* This state exists for an incoming call for the point-to-multipoint
* configuration when the call is being cleared before any user has been
* awarded the call.
*/
Q931_CALL_STATE_CALL_ABORT = 22,
/*!
* \details
* overlap receiving (U25):
* This state exists for an incoming call when the user has acknowledged
* the call establishment request from the network and is prepared to
* receive additional call information (if any) in overlap mode.
* \details
* overlap receiving (N25):
* This state exists for an incoming call when the network has received
* acknowledgement of the call establishment request which permits the
* network to send additional call information (if any) in the overlap
* mode.
*/
Q931_CALL_STATE_OVERLAP_RECEIVING = 25,
/*!
* \details
* call independent service (U31): (From Q.932)
* This state exists when a call independent supplementary service
* signalling connection is established.
* \details
* call independent service (N31): (From Q.932)
* This state exists when a call independent supplementary service
* signalling connection is established.
*/
Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE = 31,
Q931_CALL_STATE_RESTART_REQUEST = 61,
Q931_CALL_STATE_RESTART = 62,
/*!
* \details
* Call state has not been set.
* Call state does not exist.
* Call state not initialized.
* Call state internal use only.
*/
Q931_CALL_STATE_NOT_SET = 0xFF,
};
/* Call state stuff */
#define Q931_CALL_STATE_NULL 0
#define Q931_CALL_STATE_CALL_INITIATED 1
#define Q931_CALL_STATE_OVERLAP_SENDING 2
#define Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING 3
#define Q931_CALL_STATE_CALL_DELIVERED 4
#define Q931_CALL_STATE_CALL_PRESENT 6
#define Q931_CALL_STATE_CALL_RECEIVED 7
#define Q931_CALL_STATE_CONNECT_REQUEST 8
#define Q931_CALL_STATE_INCOMING_CALL_PROCEEDING 9
#define Q931_CALL_STATE_ACTIVE 10
#define Q931_CALL_STATE_DISCONNECT_REQUEST 11
#define Q931_CALL_STATE_DISCONNECT_INDICATION 12
#define Q931_CALL_STATE_SUSPEND_REQUEST 15
#define Q931_CALL_STATE_RESUME_REQUEST 17
#define Q931_CALL_STATE_RELEASE_REQUEST 19
#define Q931_CALL_STATE_OVERLAP_RECEIVING 25
#define Q931_CALL_STATE_RESTART_REQUEST 61
#define Q931_CALL_STATE_RESTART 62
/*! Q.931 call establishment state ranking for competing calls in PTMP NT mode. */
enum Q931_RANKED_CALL_STATE {
/*! Call is present but has no response yet. */
Q931_RANKED_CALL_STATE_PRESENT,
/*! Call is collecting digits. */
Q931_RANKED_CALL_STATE_OVERLAP,
/*! Call routing is happening. */
Q931_RANKED_CALL_STATE_PROCEEDING,
/*! Called party is being alerted of the call. */
Q931_RANKED_CALL_STATE_ALERTING,
/*! Call is connected. A winner has been declared. */
Q931_RANKED_CALL_STATE_CONNECT,
/*! Call is in some non-call establishment state (likely disconnecting). */
Q931_RANKED_CALL_STATE_OTHER,
};
/* EuroISDN */
#define Q931_SENDING_COMPLETE 0xa1
extern int maintenance_service(struct pri *pri, int span, int channel, int changestatus);
extern int maintenance_service_ack(struct pri *pri, q931_call *call);
/* Q.SIG specific */
#define QSIG_IE_TRANSIT_COUNT 0x31
extern int q931_receive(struct pri *pri, int tei, q931_h *h, int len);
extern int q931_receive(struct pri *pri, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
extern int q931_call_progress_with_cause(struct pri *pri, q931_call *call, int channel, int info, int cause);
extern int q931_call_progress(struct pri *pri, q931_call *call, int channel, int info);
extern int q931_notify(struct pri *pri, q931_call *call, int channel, int info);
@@ -468,8 +256,6 @@ extern int q931_setup_ack(struct pri *pri, q931_call *call, int channel, int non
extern int q931_information(struct pri *pri, q931_call *call, char digit);
extern int q931_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
extern int q931_release(struct pri *pri, q931_call *call, int cause);
@@ -480,28 +266,15 @@ extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
extern int q931_restart(struct pri *pri, int channel);
extern int q931_facility(struct pri *pri, q931_call *call);
extern int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode);
extern int q931_call_setcrv(struct pri *pri, q931_call *call, int crv, int callmode);
struct q931_call *q931_find_call(struct pri *ctrl, int cr);
struct q931_call *q931_new_call(struct pri *pri);
extern q931_call *q931_new_call(struct pri *pri);
extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx);
void q931_destroycall(struct pri *pri, q931_call *c);
extern void q931_dl_indication(struct pri *pri, int event);
int q931_send_hold(struct pri *ctrl, struct q931_call *call);
int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);
int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause);
int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel);
int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel);
int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause);
extern void q931_dump(q931_h *h, int len, int txrx);
extern void __q931_destroycall(struct pri *pri, q931_call *c);
#endif

View File

@@ -1,30 +1,25 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001-2005, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*
@@ -42,7 +37,11 @@
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <zaptel/zaptel.h>
#if defined(__linux__)
#include <linux/zaptel.h>
#elif defined(__FreeBSD__)
#include <zaptel.h>
#endif
#include "libpri.h"
#include "pri_q921.h"
#include "pri_q931.h"
@@ -68,12 +67,12 @@ static int pri_open(char *dev)
return dfd;
}
static void dump_packet(struct pri *pri, char *buf, int len, int txrx)
static void dump_packet(char *buf, int len, int txrx)
{
q921_h *h = (q921_h *)buf;
q921_dump(pri, h, len, 1, txrx);
q921_dump(h, len, 1, txrx);
if (!((h->h.data[0] & Q921_FRAMETYPE_MASK) & 0x3)) {
q931_dump(pri, h->h.tei, (q931_h *)(h->i.data), len - 4 - 2 /* FCS */, txrx);
q931_dump((q931_h *)(h->i.data), len - 4, txrx);
}
fflush(stdout);
fflush(stderr);
@@ -104,28 +103,18 @@ static int pri_bridge(int d1, int d2)
if (FD_ISSET(d1, &fds)) {
/* Copy from d1 to d2 */
res = read(d1, buf, sizeof(buf));
dump_packet((struct pri *)NULL, buf, res, 1);
dump_packet(buf, res, 1);
res = write(d2, buf, res);
}
if (FD_ISSET(d2, &fds)) {
/* Copy from d2 to d1 */
res = read(d2, buf, sizeof(buf));
dump_packet((struct pri *)NULL, buf, res, 0);
dump_packet(buf, res, 0);
res = write(d1, buf, res);
}
}
}
static void my_pri_message(struct pri *pri, char *stuff)
{
fprintf(stdout, "%s", stuff);
}
static void my_pri_error(struct pri *pri, char *stuff)
{
fprintf(stderr, "%s", stuff);
}
int main(int argc, char *argv[])
{
int d1, d2;
@@ -135,9 +124,6 @@ int main(int argc, char *argv[])
exit(1);
}
pri_set_message(my_pri_message);
pri_set_error(my_pri_error);
d1 = pri_open(argv[1]);
if (d1 < 0)
exit(1);

View File

@@ -1,75 +1,48 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001-2005, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
#include <stdio.h>
#include "libpri.h"
#include "pri_internal.h"
#include <stdio.h>
/*! \brief The maximum number of timers that were active at once. */
static int maxsched = 0;
/* Scheduler routines */
/*!
* \brief Start a timer to schedule an event.
*
* \param ctrl D channel controller.
* \param ms Number of milliseconds to scheduled event.
* \param function Callback function to call when timeout.
* \param data Value to give callback function when timeout.
*
* \retval 0 if scheduler table is full and could not schedule the event.
* \retval id Scheduled event id.
*/
int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data)
{
int x;
struct timeval tv;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (!ctrl->pri_sched[x].callback) {
for (x=1;x<MAX_SCHED;x++)
if (!pri->pri_sched[x].callback)
break;
}
}
if (x == MAX_SCHED) {
pri_error(ctrl, "No more room in scheduler\n");
return 0;
}
if (x >= maxsched) {
maxsched = x + 1;
pri_error("No more room in scheduler\n");
return -1;
}
if (x > maxsched)
maxsched = x;
gettimeofday(&tv, NULL);
tv.tv_sec += ms / 1000;
tv.tv_usec += (ms % 1000) * 1000;
@@ -77,110 +50,69 @@ int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), v
tv.tv_usec -= 1000000;
tv.tv_sec += 1;
}
ctrl->pri_sched[x].when = tv;
ctrl->pri_sched[x].callback = function;
ctrl->pri_sched[x].data = data;
return x + 1;
pri->pri_sched[x].when = tv;
pri->pri_sched[x].callback = function;
pri->pri_sched[x].data = data;
return x;
}
/*!
* \brief Determine the time of the next scheduled event to expire.
*
* \param ctrl D channel controller.
*
* \return Time of the next scheduled event to expire or NULL if no timers active.
*/
struct timeval *pri_schedule_next(struct pri *ctrl)
struct timeval *pri_schedule_next(struct pri *pri)
{
struct timeval *closest = NULL;
int x;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (ctrl->pri_sched[x].callback && (!closest
|| (closest->tv_sec > ctrl->pri_sched[x].when.tv_sec)
|| ((closest->tv_sec == ctrl->pri_sched[x].when.tv_sec)
&& (closest->tv_usec > ctrl->pri_sched[x].when.tv_usec)))) {
closest = &ctrl->pri_sched[x].when;
}
/* Check subchannels */
if (pri->subchannel)
closest = pri_schedule_next(pri->subchannel);
for (x=1;x<MAX_SCHED;x++) {
if (pri->pri_sched[x].callback &&
(!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
((closest->tv_sec == pri->pri_sched[x].when.tv_sec) &&
(closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
closest = &pri->pri_sched[x].when;
}
return closest;
}
/*!
* \internal
* \brief Run all expired timers or return an event generated by an expired timer.
*
* \param ctrl D channel controller.
* \param tv Current time.
*
* \return Event for upper layer to process or NULL if all expired timers run.
*/
static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
{
int x;
void (*callback)(void *);
void *data;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (ctrl->pri_sched[x].callback && ((ctrl->pri_sched[x].when.tv_sec < tv->tv_sec)
|| ((ctrl->pri_sched[x].when.tv_sec == tv->tv_sec)
&& (ctrl->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
/* This timer has expired. */
ctrl->schedev = 0;
callback = ctrl->pri_sched[x].callback;
data = ctrl->pri_sched[x].data;
ctrl->pri_sched[x].callback = NULL;
callback(data);
if (ctrl->schedev) {
return &ctrl->ev;
}
pri_event *e;
if (pri->subchannel) {
if ((e = __pri_schedule_run(pri->subchannel, tv))) {
return e;
}
}
for (x=1;x<MAX_SCHED;x++) {
if (pri->pri_sched[x].callback &&
((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
(pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
pri->schedev = 0;
callback = pri->pri_sched[x].callback;
data = pri->pri_sched[x].data;
pri->pri_sched[x].callback = NULL;
pri->pri_sched[x].data = NULL;
callback(data);
if (pri->schedev)
return &pri->ev;
}
}
return NULL;
}
/*!
* \brief Run all expired timers or return an event generated by an expired timer.
*
* \param ctrl D channel controller.
*
* \return Event for upper layer to process or NULL if all expired timers run.
*/
pri_event *pri_schedule_run(struct pri *ctrl)
pri_event *pri_schedule_run(struct pri *pri)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return __pri_schedule_run(ctrl, &tv);
return __pri_schedule_run(pri, &tv);
}
/*!
* \brief Delete a scheduled event.
*
* \param ctrl D channel controller.
* \param id Scheduled event id to delete.
* 0 is a disabled/unscheduled event id that is ignored.
* 1 - MAX_SCHED is a valid event id.
*
* \return Nothing
*/
void pri_schedule_del(struct pri *ctrl, int id)
void pri_schedule_del(struct pri *pri,int id)
{
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
if (0 < id && id <= MAX_SCHED) {
ctrl->pri_sched[id - 1].callback = NULL;
} else if (id) {
pri_error(ctrl, "Asked to delete sched id %d???\n", id);
}
if ((id >= MAX_SCHED) || (id < 0))
pri_error("Asked to delete sched id %d???\n", id);
pri->pri_sched[id].callback = NULL;
}

View File

@@ -1,30 +1,25 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001-2005, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*
@@ -45,7 +40,11 @@
#include <sys/wait.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <zaptel/zaptel.h>
#if defined(__linux__)
#include <linux/zaptel.h>
#elif defined(__FreeBSD__)
#include <zaptel.h>
#endif
#include <zap.h>
#include "libpri.h"
@@ -299,7 +298,7 @@ static int run_pri(int dfd, int swtype, int node)
fd_set rfds, efds;
int res,x;
pri = pri_new_bri(dfd, 1, node, swtype);
pri = pri_new(dfd, node, swtype);
if (!pri) {
fprintf(stderr, "Unable to create PRI\n");
return -1;

2219
q921.c

File diff suppressed because it is too large Load Diff

7072
q931.c

File diff suppressed because it is too large Load Diff

2464
rose.c

File diff suppressed because it is too large Load Diff

3580
rose.h

File diff suppressed because it is too large Load Diff

View File

@@ -1,983 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief ROSE Addressing-Data-Elements
*
* Addressing-Data-Elements ETS 300 196-1 D.3
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the public or private network PartyNumber type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param number
* \param length_of_number
* \param type_of_number
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_NetworkPartyNumber(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const unsigned char *number,
size_t length_of_number, u_int8_t type_of_number)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, type_of_number));
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_NUMERIC_STRING, number,
length_of_number));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the PartyNumber type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param party_number
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePartyNumber *party_number)
{
switch (party_number->plan) {
case 0: /* Unknown PartyNumber */
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
party_number->str, party_number->length));
break;
case 1: /* Public PartyNumber */
ASN1_CALL(pos, rose_enc_NetworkPartyNumber(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 1, party_number->str, party_number->length,
party_number->ton));
break;
case 2: /* NSAP encoded PartyNumber */
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
party_number->str, party_number->length));
break;
case 3: /* Data PartyNumber (Not used) */
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
party_number->str, party_number->length));
break;
case 4: /* Telex PartyNumber (Not used) */
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4,
party_number->str, party_number->length));
break;
case 5: /* Private PartyNumber */
ASN1_CALL(pos, rose_enc_NetworkPartyNumber(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 5, party_number->str, party_number->length,
party_number->ton));
break;
case 8: /* National Standard PartyNumber (Not used) */
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 8,
party_number->str, party_number->length));
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown numbering plan");
return NULL;
}
return pos;
}
/*!
* \brief Encode the PartySubaddress type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param party_subaddress
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePartySubaddress *party_subaddress)
{
unsigned char *seq_len;
switch (party_subaddress->type) {
case 0: /* UserSpecified */
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING,
party_subaddress->u.user_specified.information, party_subaddress->length));
if (party_subaddress->u.user_specified.odd_count_present) {
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
party_subaddress->u.user_specified.odd_count));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
break;
case 1: /* NSAP */
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING,
party_subaddress->u.nsap, party_subaddress->length));
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown subaddress type");
return NULL;
}
return pos;
}
/*!
* \brief Encode the Address type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param address
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
unsigned tag, const struct roseAddress *address)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &address->number));
if (address->subaddress.length) {
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end, &address->subaddress));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the PresentedNumberUnscreened type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param party
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePresentedNumberUnscreened *party)
{
unsigned char *seq_len;
switch (party->presentation) {
case 0: /* presentationAllowedNumber */
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &party->number));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
break;
case 1: /* presentationRestricted */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
break;
case 2: /* numberNotAvailableDueToInterworking */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
break;
case 3: /* presentationRestrictedNumber */
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &party->number));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
return NULL;
}
return pos;
}
/*!
* \brief Encode the NumberScreened type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param screened
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseNumberScreened *screened)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &screened->number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
screened->screening_indicator));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the PresentedNumberScreened type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param party
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePresentedNumberScreened *party)
{
switch (party->presentation) {
case 0: /* presentationAllowedNumber */
ASN1_CALL(pos, rose_enc_NumberScreened(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 0, &party->screened));
break;
case 1: /* presentationRestricted */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
break;
case 2: /* numberNotAvailableDueToInterworking */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
break;
case 3: /* presentationRestrictedNumber */
ASN1_CALL(pos, rose_enc_NumberScreened(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 3, &party->screened));
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
return NULL;
}
return pos;
}
/*!
* \brief Encode the AddressScreened type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param screened
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseAddressScreened *screened)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &screened->number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
screened->screening_indicator));
if (screened->subaddress.length) {
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end, &screened->subaddress));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the PresentedAddressScreened type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param party
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePresentedAddressScreened *party)
{
switch (party->presentation) {
case 0: /* presentationAllowedAddress */
ASN1_CALL(pos, rose_enc_AddressScreened(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 0, &party->screened));
break;
case 1: /* presentationRestricted */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
break;
case 2: /* numberNotAvailableDueToInterworking */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
break;
case 3: /* presentationRestrictedAddress */
ASN1_CALL(pos, rose_enc_AddressScreened(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 3, &party->screened));
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
return NULL;
}
return pos;
}
/*!
* \internal
* \brief Decode the NumberDigits PartyNumber argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_number Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_NumberDigits(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartyNumber *party_number)
{
size_t str_len;
ASN1_CALL(pos, asn1_dec_string_max(ctrl, name, tag, pos, end,
sizeof(party_number->str), party_number->str, &str_len));
party_number->length = str_len;
return pos;
}
/*!
* \internal
* \brief Decode the NSAP PartyNumber argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_number Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_NSAPPartyNumber(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartyNumber *party_number)
{
size_t str_len;
ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
sizeof(party_number->str), party_number->str, &str_len));
party_number->length = str_len;
return pos;
}
/*!
* \internal
* \brief Decode the public or private network PartyNumber argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_number Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_NetworkPartyNumber(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartyNumber *party_number)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfNumber", tag, pos, seq_end, &value));
party_number->ton = value;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_NUMERIC_STRING);
ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "numberDigits", tag, pos, seq_end,
party_number));
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the PartyNumber argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_number Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartyNumber *party_number)
{
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s PartyNumber\n", name);
}
party_number->ton = 0; /* unknown */
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
party_number->plan = 0; /* Unknown PartyNumber */
ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "unknownPartyNumber", tag, pos, end,
party_number));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
/* Must be constructed but we will not check for it for simplicity. */
party_number->plan = 1; /* Public PartyNumber */
ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "publicPartyNumber", tag, pos,
end, party_number));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
party_number->plan = 2; /* NSAP encoded PartyNumber */
ASN1_CALL(pos, rose_dec_NSAPPartyNumber(ctrl, "nsapEncodedPartyNumber", tag, pos,
end, party_number));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
party_number->plan = 3; /* Data PartyNumber (Not used) */
ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "dataPartyNumber", tag, pos, end,
party_number));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
party_number->plan = 4; /* Telex PartyNumber (Not used) */
ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "telexPartyNumber", tag, pos, end,
party_number));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
/* Must be constructed but we will not check for it for simplicity. */
party_number->plan = 5; /* Private PartyNumber */
ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "privatePartyNumber", tag, pos,
end, party_number));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 8:
party_number->plan = 8; /* National Standard PartyNumber (Not used) */
ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "nationalStandardPartyNumber", tag,
pos, end, party_number));
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/*!
* \internal
* \brief Decode the User PartySubaddress argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_subaddress Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_UserSubaddress(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartySubaddress *party_subaddress)
{
size_t str_len;
int32_t odd_count;
int length;
int seq_offset;
const unsigned char *seq_end;
party_subaddress->type = 0; /* UserSpecified */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s UserSpecified %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/* SubaddressInformation */
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING);
ASN1_CALL(pos, asn1_dec_string_bin(ctrl, "subaddressInformation", tag, pos, seq_end,
sizeof(party_subaddress->u.user_specified.information),
party_subaddress->u.user_specified.information, &str_len));
party_subaddress->length = str_len;
if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
/*
* The optional odd count indicator must be present since there
* is something left.
*/
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "oddCount", tag, pos, seq_end,
&odd_count));
party_subaddress->u.user_specified.odd_count = odd_count;
party_subaddress->u.user_specified.odd_count_present = 1;
} else {
party_subaddress->u.user_specified.odd_count = 0;
party_subaddress->u.user_specified.odd_count_present = 0;
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \internal
* \brief Decode the NSAP PartySubaddress argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_subaddress Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_NSAPSubaddress(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartySubaddress *party_subaddress)
{
size_t str_len;
party_subaddress->type = 1; /* NSAP */
ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
sizeof(party_subaddress->u.nsap), party_subaddress->u.nsap, &str_len));
party_subaddress->length = str_len;
return pos;
}
/*!
* \brief Decode the PartySubaddress argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party_subaddress Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartySubaddress *party_subaddress)
{
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s PartySubaddress\n", name);
}
switch (tag) {
case ASN1_TAG_SEQUENCE:
ASN1_CALL(pos, rose_dec_UserSubaddress(ctrl, "user", tag, pos, end,
party_subaddress));
break;
case ASN1_TYPE_OCTET_STRING:
case ASN1_TYPE_OCTET_STRING | ASN1_PC_CONSTRUCTED:
ASN1_CALL(pos, rose_dec_NSAPSubaddress(ctrl, "nsap", tag, pos, end,
party_subaddress));
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/*!
* \brief Decode the Address argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param address Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, struct roseAddress *address)
{
int length;
int seq_offset;
const unsigned char *seq_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s Address %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
&address->number));
if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
/* The optional subaddress must be present since there is something left. */
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos,
seq_end, &address->subaddress));
} else {
address->subaddress.length = 0; /* Subaddress not present */
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the PresentedNumberUnscreened argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePresentedNumberUnscreened *party)
{
int length;
int seq_offset;
const unsigned char *seq_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s PresentedNumberUnscreened\n", name);
}
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
party->presentation = 0; /* presentationAllowedNumber */
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationAllowedNumber", tag, pos,
seq_end, &party->number));
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
party->presentation = 1; /* presentationRestricted */
ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
party->presentation = 2; /* numberNotAvailableDueToInterworking */
ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
party->presentation = 3; /* presentationRestrictedNumber */
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationRestrictedNumber", tag,
pos, seq_end, &party->number));
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/*!
* \brief Decode the NumberScreened argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param screened Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseNumberScreened *screened)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s NumberScreened %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
&screened->number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value));
screened->screening_indicator = value;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the PresentedNumberScreened argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePresentedNumberScreened *party)
{
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s PresentedNumberScreened\n", name);
}
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
party->presentation = 0; /* presentationAllowedNumber */
ASN1_CALL(pos, rose_dec_NumberScreened(ctrl, "presentationAllowedNumber", tag,
pos, end, &party->screened));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
party->presentation = 1; /* presentationRestricted */
ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
party->presentation = 2; /* numberNotAvailableDueToInterworking */
ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
party->presentation = 3; /* presentationRestrictedNumber */
ASN1_CALL(pos, rose_dec_NumberScreened(ctrl, "presentationRestrictedNumber", tag,
pos, end, &party->screened));
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/*!
* \brief Decode the AddressScreened argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param screened Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseAddressScreened *screened)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s AddressScreened %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
&screened->number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value));
screened->screening_indicator = value;
if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
/* The optional subaddress must be present since there is something left. */
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos,
seq_end, &screened->subaddress));
} else {
screened->subaddress.length = 0; /* Subaddress not present */
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the PresentedAddressScreened argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePresentedAddressScreened *party)
{
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s PresentedAddressScreened\n", name);
}
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
party->presentation = 0; /* presentationAllowedAddress */
ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationAllowedAddress", tag,
pos, end, &party->screened));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
party->presentation = 1; /* presentationRestricted */
ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
party->presentation = 2; /* numberNotAvailableDueToInterworking */
ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
party->presentation = 3; /* presentationRestrictedAddress */
ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationRestrictedAddress",
tag, pos, end, &party->screened));
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_address.c */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,332 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief ROSE Explicit Call Transfer operations.
*
* Explicit Call Transfer (ECT) Supplementary Services ETS 300 369-1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \brief Encode the ExplicitEctExecute invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
args->etsi.ExplicitEctExecute.link_id);
}
/*!
* \brief Encode the SubaddressTransfer invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_PartySubaddress(ctrl, pos, end,
&args->etsi.SubaddressTransfer.subaddress);
}
/*!
* \brief Encode the EctLinkIdRequest result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
args->etsi.EctLinkIdRequest.link_id);
}
/*!
* \brief Encode the EctInform invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiEctInform_ARG *ect_inform;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ect_inform = &args->etsi.EctInform;
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, ect_inform->status));
if (ect_inform->redirection_present) {
ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
&ect_inform->redirection));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the EctLoopTest invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
args->etsi.EctLoopTest.call_transfer_id);
}
/*!
* \brief Encode the EctLoopTest result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
args->etsi.EctLoopTest.loop_result);
}
/*!
* \brief Decode the ExplicitEctExecute invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "linkId", tag, pos, end, &value));
args->etsi.ExplicitEctExecute.link_id = value;
return pos;
}
/*!
* \brief Decode the SubaddressTransfer invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_PartySubaddress(ctrl, "transferredToSubaddress", tag, pos, end,
&args->etsi.SubaddressTransfer.subaddress);
}
/*!
* \brief Decode the EctLinkIdRequest result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
int32_t value;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "linkId", tag, pos, end, &value));
args->etsi.EctLinkIdRequest.link_id = value;
return pos;
}
/*!
* \brief Decode the EctInform invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
struct roseEtsiEctInform_ARG *ect_inform;
int length;
int seq_offset;
const unsigned char *seq_end;
int32_t value;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " EctInform %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ect_inform = &args->etsi.EctInform;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value));
ect_inform->status = value;
if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "redirectionNumber", tag,
pos, seq_end, &ect_inform->redirection));
ect_inform->redirection_present = 1;
} else {
ect_inform->redirection_present = 0;
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the EctLoopTest invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "callTransferId", tag, pos, end, &value));
args->etsi.EctLoopTest.call_transfer_id = value;
return pos;
}
/*!
* \brief Decode the EctLoopTest result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
int32_t value;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "loopResult", tag, pos, end, &value));
args->etsi.EctLoopTest.loop_result = value;
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_etsi_ect.c */

View File

@@ -1,477 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Internal definitions and prototypes for ROSE.
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#ifndef _LIBPRI_ROSE_INTERNAL_H
#define _LIBPRI_ROSE_INTERNAL_H
#include "rose.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ------------------------------------------------------------------- */
/* Embedded-Q931-Types */
unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
unsigned tag, const struct roseQ931ie *q931ie);
const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
size_t contents_size);
/* Addressing-Data-Elements */
unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePartyNumber *party_number);
unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePartySubaddress *party_subaddress);
unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
unsigned tag, const struct roseAddress *address);
unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePresentedNumberUnscreened *party);
unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseNumberScreened *screened);
unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePresentedNumberScreened *party);
unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseAddressScreened *screened);
unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct rosePresentedAddressScreened *party);
const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartyNumber *party_number);
const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePartySubaddress *party_subaddress);
const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, struct roseAddress *address);
const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePresentedNumberUnscreened *party);
const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseNumberScreened *screened);
const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePresentedNumberScreened *party);
const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseAddressScreened *screened);
const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct rosePresentedAddressScreened *party);
/* ETSI Advice-of-Charge (AOC) */
unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* ETSI Call Diversion */
unsigned char *rose_enc_etsi_ActivationDiversion_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_DeactivationStatusNotificationDiv_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_InterrogationDiversion_RES(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_DiversionInformation_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_ActivationDiversion_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_DeactivationStatusNotificationDiv_ARG(struct pri
*ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_InterrogationDiversion_RES(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_DiversionInformation_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* ETSI Explicit Call Transfer (ECT) */
unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* Q.SIG Name-Operations */
unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigName *name);
const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigName *name);
unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/*
* Q.SIG Dummy invoke/result argument used by:
* SS-AOC-Operations,
* Call-Transfer-Operations,
* Call-Diversion-Operations,
* and SS-MWI-Operations.
*/
unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* Q.SIG SS-AOC-Operations */
unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG Call-Diversion-Operations */
unsigned char *rose_enc_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG Call-Transfer-Operations (CT) */
unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG SS-MWI-Operations */
unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* Northern Telecom DMS-100 operations */
unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* National ISDN 2 (NI2) operations */
unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* ------------------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* _LIBPRI_ROSE_INTERNAL_H */
/* ------------------------------------------------------------------- */
/* end rose_internal.h */

View File

@@ -1,277 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Switch type operations for: NI2, 4ESS, 5ESS, DMS-100
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \brief Encode the DMS-100 RLT_OperationInd result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
args->dms100.RLT_OperationInd.call_id);
}
/*!
* \brief Encode the DMS-100 RLT_ThirdParty invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseDms100RLTThirdParty_ARG *rlt_thirdparty;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
rlt_thirdparty = &args->dms100.RLT_ThirdParty;
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
rlt_thirdparty->call_id));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
rlt_thirdparty->reason));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Decode the DMS-100 RLT_OperationInd result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
int32_t value;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, end, &value));
args->dms100.RLT_OperationInd.call_id = value;
return pos;
}
/*!
* \brief Decode the DMS-100 RLT_ThirdParty invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseDms100RLTThirdParty_ARG *rlt_third_party;
rlt_third_party = &args->dms100.RLT_ThirdParty;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " RLT_ThirdParty %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, seq_end, &value));
rlt_third_party->call_id = value;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
ASN1_CALL(pos, asn1_dec_int(ctrl, "reason", tag, pos, seq_end, &value));
rlt_third_party->reason = value;
/* Fixup will skip over any OPTIONAL information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Encode the NI2 InformationFollowing invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
{
/* Encode the unknown enumeration value. */
return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
args->ni2.InformationFollowing.value);
}
/*!
* \brief Encode the NI2 InitiateTransfer invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseNi2InitiateTransfer_ARG *initiate_transfer;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
initiate_transfer = &args->ni2.InitiateTransfer;
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
initiate_transfer->call_reference));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Decode the NI2 InformationFollowing invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "unknown", tag, pos, end, &value));
args->ni2.InformationFollowing.value = value;
return pos;
}
/*!
* \brief Decode the NI2 InitiateTransfer invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseNi2InitiateTransfer_ARG *initiate_transfer;
initiate_transfer = &args->ni2.InitiateTransfer;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " InitiateTransfer %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "callReference", tag, pos, seq_end, &value));
initiate_transfer->call_reference = value;
/* Fixup will skip over any OPTIONAL information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_other.c */

View File

@@ -1,100 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief ROSE Q.931 ie encode/decode functions
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \brief Encode the Q.931 ie value.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_CLASS_APPLICATION | 0 unless the caller
* implicitly tags it otherwise.
* \param q931ie Q931 ie information to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
unsigned tag, const struct roseQ931ie *q931ie)
{
return asn1_enc_string_bin(pos, end, tag, q931ie->contents, q931ie->length);
}
/*!
* \brief Decode the Q.931 ie value.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param q931ie Parameter storage to fill.
* \param contents_size Amount of space "allocated" for the q931ie->contents
* element. Must have enough room for a null terminator.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
size_t contents_size)
{
size_t str_len;
/* NOTE: The q931ie->contents memory is "allocated" after the struct. */
ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end, contents_size,
q931ie->contents, &str_len));
q931ie->length = str_len;
/*
* NOTE: We may want to do some basic decoding of the Q.931 ie list
* for debug purposes.
*/
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_q931.c */

File diff suppressed because it is too large Load Diff

View File

@@ -1,883 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Q.SIG ROSE Call-Transfer-Operations (CT)
*
* Call-Transfer-Operations ECMA-178 Annex F Table F.1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \brief Encode the Q.SIG CallTransferIdentify result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
{
unsigned char *seq_len;
const struct roseQsigCTIdentifyRes_RES *call_transfer_identify;
call_transfer_identify = &args->qsig.CallTransferIdentify;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
call_transfer_identify->call_id, sizeof(call_transfer_identify->call_id) - 1));
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&call_transfer_identify->rerouting_number));
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CallTransferInitiate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
{
unsigned char *seq_len;
const struct roseQsigCTInitiateArg_ARG *call_transfer_initiate;
call_transfer_initiate = &args->qsig.CallTransferInitiate;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
call_transfer_initiate->call_id, sizeof(call_transfer_initiate->call_id) - 1));
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&call_transfer_initiate->rerouting_number));
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CallTransferSetup invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
unsigned char *seq_len;
const struct roseQsigCTSetupArg_ARG *call_transfer_setup;
call_transfer_setup = &args->qsig.CallTransferSetup;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
call_transfer_setup->call_id, sizeof(call_transfer_setup->call_id) - 1));
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CallTransferActive invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
unsigned char *seq_len;
const struct roseQsigCTActiveArg_ARG *call_transfer_active;
call_transfer_active = &args->qsig.CallTransferActive;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, rose_enc_PresentedAddressScreened(ctrl, pos, end,
&call_transfer_active->connected));
if (call_transfer_active->q931ie.length) {
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&call_transfer_active->q931ie));
}
if (call_transfer_active->connected_name_present) {
ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
&call_transfer_active->connected_name));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CallTransferComplete invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
{
unsigned char *seq_len;
const struct roseQsigCTCompleteArg_ARG *call_transfer_complete;
call_transfer_complete = &args->qsig.CallTransferComplete;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
call_transfer_complete->end_designation));
ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
&call_transfer_complete->redirection));
if (call_transfer_complete->q931ie.length) {
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&call_transfer_complete->q931ie));
}
if (call_transfer_complete->redirection_name_present) {
ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
&call_transfer_complete->redirection_name));
}
if (call_transfer_complete->call_status) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
call_transfer_complete->call_status));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CallTransferUpdate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
unsigned char *seq_len;
const struct roseQsigCTUpdateArg_ARG *call_transfer_update;
call_transfer_update = &args->qsig.CallTransferUpdate;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
&call_transfer_update->redirection));
if (call_transfer_update->redirection_name_present) {
ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
&call_transfer_update->redirection_name));
}
if (call_transfer_update->q931ie.length) {
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&call_transfer_update->q931ie));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG SubaddressTransfer invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
unsigned char *seq_len;
const struct roseQsigSubaddressTransferArg_ARG *subaddress_transfer;
subaddress_transfer = &args->qsig.SubaddressTransfer;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&subaddress_transfer->redirection_subaddress));
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG DummyArg invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*
* \details
* DummyArg ::= CHOICE {
* none NULL,
* extension [1] IMPLICIT Extension,
* multipleExtension [2] IMPLICIT SEQUENCE OF Extension
* }
*/
unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
}
/*!
* \brief Encode the Q.SIG DummyRes result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*
* \details
* DummyRes ::= CHOICE {
* none NULL,
* extension [1] IMPLICIT Extension,
* multipleExtension [2] IMPLICIT SEQUENCE OF Extension
* }
*/
unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
}
/*!
* \brief Decode the Q.SIG CallTransferIdentify result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args)
{
size_t str_len;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseQsigCTIdentifyRes_RES *call_transfer_identify;
call_transfer_identify = &args->qsig.CallTransferIdentify;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " CallTransferIdentify %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
sizeof(call_transfer_identify->call_id), call_transfer_identify->call_id,
&str_len));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "reroutingNumber", tag, pos, seq_end,
&call_transfer_identify->rerouting_number));
/* Fixup will skip over any OPTIONAL manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CallTransferInitiate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
size_t str_len;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseQsigCTInitiateArg_ARG *call_transfer_initiate;
call_transfer_initiate = &args->qsig.CallTransferInitiate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " CallTransferInitiate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
sizeof(call_transfer_initiate->call_id), call_transfer_initiate->call_id,
&str_len));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "reroutingNumber", tag, pos, seq_end,
&call_transfer_initiate->rerouting_number));
/* Fixup will skip over any OPTIONAL manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CallTransferSetup invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
size_t str_len;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseQsigCTSetupArg_ARG *call_transfer_setup;
call_transfer_setup = &args->qsig.CallTransferSetup;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " CallTransferSetup %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
sizeof(call_transfer_setup->call_id), call_transfer_setup->call_id, &str_len));
/* Fixup will skip over any OPTIONAL manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CallTransferActive invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseQsigCTActiveArg_ARG *call_transfer_active;
call_transfer_active = &args->qsig.CallTransferActive;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " CallTransferActive %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PresentedAddressScreened(ctrl, "connectedAddress", tag, pos,
seq_end, &call_transfer_active->connected));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
call_transfer_active->q931ie.length = 0;
call_transfer_active->connected_name_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_APPLICATION | 0:
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
seq_end, &call_transfer_active->q931ie,
sizeof(call_transfer_active->q931ie_contents)));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "connectedName", tag, pos, seq_end,
&call_transfer_active->connected_name));
call_transfer_active->connected_name_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CallTransferComplete invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
unsigned tag, const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseQsigCTCompleteArg_ARG *call_transfer_complete;
call_transfer_complete = &args->qsig.CallTransferComplete;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " CallTransferComplete %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "endDesignation", tag, pos, seq_end, &value));
call_transfer_complete->end_designation = value;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "redirectionNumber", tag, pos,
seq_end, &call_transfer_complete->redirection));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
call_transfer_complete->q931ie.length = 0;
call_transfer_complete->redirection_name_present = 0;
call_transfer_complete->call_status = 0; /* DEFAULT answered */
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_APPLICATION | 0:
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
seq_end, &call_transfer_complete->q931ie,
sizeof(call_transfer_complete->q931ie_contents)));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos, seq_end,
&call_transfer_complete->redirection_name));
call_transfer_complete->redirection_name_present = 1;
break;
case ASN1_TYPE_ENUMERATED:
/* Must not be constructed but we will not check for it for simplicity. */
ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value));
call_transfer_complete->call_status = value;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CallTransferUpdate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseQsigCTUpdateArg_ARG *call_transfer_update;
call_transfer_update = &args->qsig.CallTransferUpdate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " CallTransferUpdate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "redirectionNumber", tag, pos,
seq_end, &call_transfer_update->redirection));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
call_transfer_update->redirection_name_present = 0;
call_transfer_update->q931ie.length = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos, seq_end,
&call_transfer_update->redirection_name));
call_transfer_update->redirection_name_present = 1;
break;
case ASN1_CLASS_APPLICATION | 0:
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
seq_end, &call_transfer_update->q931ie,
sizeof(call_transfer_update->q931ie_contents)));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG SubaddressTransfer invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseQsigSubaddressTransferArg_ARG *subaddress_transfer;
subaddress_transfer = &args->qsig.SubaddressTransfer;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " SubaddressTransfer %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "redirectionSubaddress", tag, pos,
seq_end, &subaddress_transfer->redirection_subaddress));
/* Fixup will skip over any OPTIONAL manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG DummyArg invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*
* \details
* DummyArg ::= CHOICE {
* none NULL,
* extension [1] IMPLICIT Extension,
* multipleExtension [2] IMPLICIT SEQUENCE OF Extension
* }
*/
const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
const char *name;
int length;
int seq_offset;
const unsigned char *seq_end;
switch (tag) {
case ASN1_TYPE_NULL:
return asn1_dec_null(ctrl, "none", tag, pos, end);
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
name = "extension Extension";
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
name = "multipleExtension SEQUENCE OF Extension";
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/* Fixup will skip over the manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG DummyRes result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*
* \details
* DummyRes ::= CHOICE {
* none NULL,
* extension [1] IMPLICIT Extension,
* multipleExtension [2] IMPLICIT SEQUENCE OF Extension
* }
*/
const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
const char *name;
int length;
int seq_offset;
const unsigned char *seq_end;
switch (tag) {
case ASN1_TYPE_NULL:
return asn1_dec_null(ctrl, "none", tag, pos, end);
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
name = "extension Extension";
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
name = "multipleExtension SEQUENCE OF Extension";
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/* Fixup will skip over the manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_qsig_ct.c */

File diff suppressed because it is too large Load Diff

View File

@@ -1,790 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Q.SIG ROSE SS-MWI-Operations
*
* SS-MWI-Operations ECMA-242 Annex E Table E.1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the MsgCentreId type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param msg_centre_id
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_MsgCentreId(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigMsgCentreId *msg_centre_id)
{
unsigned char *seq_len;
switch (msg_centre_id->type) {
case 0: /* integer */
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
msg_centre_id->u.integer));
break;
case 1: /* partyNumber */
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &msg_centre_id->u.number));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
break;
case 2: /* numericString */
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
msg_centre_id->u.str, sizeof(msg_centre_id->u.str) - 1));
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown MsgCentreId type");
return NULL;
}
return pos;
}
/*!
* \brief Encode the MWIActivate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseQsigMWIActivateArg *mwi_activate;
unsigned char *seq_len;
unsigned char *explicit_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_activate = &args->qsig.MWIActivate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->served_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_activate->basic_service));
if (mwi_activate->msg_centre_id_present) {
ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
&mwi_activate->msg_centre_id));
}
if (mwi_activate->number_of_messages_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
mwi_activate->number_of_messages));
}
if (mwi_activate->originating_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->originating_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->timestamp_present) {
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_activate->timestamp, sizeof(mwi_activate->timestamp) - 1));
}
if (mwi_activate->priority_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
mwi_activate->priority));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIDeactivate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseQsigMWIDeactivateArg *mwi_deactivate;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_deactivate = &args->qsig.MWIDeactivate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_deactivate->served_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_deactivate->basic_service));
if (mwi_deactivate->msg_centre_id_present) {
ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
&mwi_deactivate->msg_centre_id));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIInterrogate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseQsigMWIInterrogateArg *mwi_interrogate;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_interrogate = &args->qsig.MWIInterrogate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_interrogate->served_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_interrogate->basic_service));
if (mwi_interrogate->msg_centre_id_present) {
ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
&mwi_interrogate->msg_centre_id));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \internal
* \brief Encode the MWIInterrogateResElt type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param record
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_MWIInterrogateResElt(struct pri *ctrl,
unsigned char *pos, unsigned char *end, unsigned tag,
const struct roseQsigMWIInterrogateResElt *record)
{
unsigned char *seq_len;
unsigned char *explicit_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, record->basic_service));
if (record->msg_centre_id_present) {
ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
&record->msg_centre_id));
}
if (record->number_of_messages_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
record->number_of_messages));
}
if (record->originating_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&record->originating_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (record->timestamp_present) {
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
record->timestamp, sizeof(record->timestamp) - 1));
}
if (record->priority_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
record->priority));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIInterrogate result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
unsigned index;
unsigned char *seq_len;
const struct roseQsigMWIInterrogateRes *mwi_interrogate;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_interrogate = &args->qsig.MWIInterrogate;
for (index = 0; index < mwi_interrogate->num_records; ++index) {
ASN1_CALL(pos, rose_enc_qsig_MWIInterrogateResElt(ctrl, pos, end,
ASN1_TAG_SEQUENCE, &mwi_interrogate->list[index]));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \internal
* \brief Decode the MsgCentreId argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param msg_centre_id Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_MsgCentreId(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigMsgCentreId *msg_centre_id)
{
int32_t value;
size_t str_len;
int length;
int explicit_offset;
const unsigned char *explicit_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s MsgCentreId\n", name);
}
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
msg_centre_id->type = 0; /* integer */
ASN1_CALL(pos, asn1_dec_int(ctrl, "integer", tag, pos, end, &value));
msg_centre_id->u.integer = value;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
msg_centre_id->type = 1; /* partyNumber */
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, explicit_end,
&msg_centre_id->u.number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
msg_centre_id->type = 2; /* numericString */
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "numericString", tag, pos, end,
sizeof(msg_centre_id->u.str), msg_centre_id->u.str, &str_len));
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/*!
* \brief Decode the Q.SIG MWIActivate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
size_t str_len;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseQsigMWIActivateArg *mwi_activate;
mwi_activate = &args->qsig.MWIActivate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIActivateArg %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
&mwi_activate->served_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_activate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_activate->msg_centre_id_present = 0;
mwi_activate->number_of_messages_present = 0;
mwi_activate->originating_number.length = 0;
mwi_activate->timestamp_present = 0;
mwi_activate->priority_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
seq_end, &mwi_activate->msg_centre_id));
mwi_activate->msg_centre_id_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
/* Must not be constructed but we will not check for it for simplicity. */
ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
&value));
mwi_activate->number_of_messages = value;
mwi_activate->number_of_messages_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
/* Must be constructed but we will not check for it for simplicity. */
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
explicit_end, &mwi_activate->originating_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_TYPE_GENERALIZED_TIME:
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
sizeof(mwi_activate->timestamp), mwi_activate->timestamp, &str_len));
mwi_activate->timestamp_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
/* Must not be constructed but we will not check for it for simplicity. */
ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
mwi_activate->priority = value;
mwi_activate->priority_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG MWIDeactivate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseQsigMWIDeactivateArg *mwi_deactivate;
mwi_deactivate = &args->qsig.MWIDeactivate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIDeactivateArg %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
&mwi_deactivate->served_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_deactivate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_deactivate->msg_centre_id_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
seq_end, &mwi_deactivate->msg_centre_id));
mwi_deactivate->msg_centre_id_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG MWIInterrogate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseQsigMWIInterrogateArg *mwi_interrogate;
mwi_interrogate = &args->qsig.MWIInterrogate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIInterrogateArg %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
&mwi_interrogate->served_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_interrogate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_interrogate->msg_centre_id_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
seq_end, &mwi_interrogate->msg_centre_id));
mwi_interrogate->msg_centre_id_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \internal
* \brief Decode the MWIInterrogateResElt argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param record Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_MWIInterrogateResElt(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigMWIInterrogateResElt *record)
{
int32_t value;
size_t str_len;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIInterrogateResElt %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
record->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
record->msg_centre_id_present = 0;
record->number_of_messages_present = 0;
record->originating_number.length = 0;
record->timestamp_present = 0;
record->priority_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
seq_end, &record->msg_centre_id));
record->msg_centre_id_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
/* Must not be constructed but we will not check for it for simplicity. */
ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
&value));
record->number_of_messages = value;
record->number_of_messages_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
/* Must be constructed but we will not check for it for simplicity. */
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
explicit_end, &record->originating_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_TYPE_GENERALIZED_TIME:
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
sizeof(record->timestamp), record->timestamp, &str_len));
record->timestamp_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
/* Must not be constructed but we will not check for it for simplicity. */
ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
record->priority = value;
record->priority_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
}
/* Fixup will skip over the manufacturer extension information */
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG MWIInterrogate result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseQsigMWIInterrogateRes *mwi_interrogate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIInterrogateRes %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
mwi_interrogate = &args->qsig.MWIInterrogate;
mwi_interrogate->num_records = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
if (mwi_interrogate->num_records < ARRAY_LEN(mwi_interrogate->list)) {
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, rose_dec_qsig_MWIInterrogateResElt(ctrl, "listEntry", tag,
pos, seq_end, &mwi_interrogate->list[mwi_interrogate->num_records]));
++mwi_interrogate->num_records;
} else {
/* Too many records */
return NULL;
}
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_qsig_mwi.c */

View File

@@ -1,474 +0,0 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Q.SIG ROSE Name operations and elements
*
* Name-Operations ECMA-164 Annex C
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the Q.SIG NameSet type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller
* implicitly tags it otherwise.
* \param name
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_NameSet(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseQsigName *name)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING, name->data,
name->length));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, name->char_set));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG Name type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param name
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigName *name)
{
switch (name->presentation) {
case 0: /* optional_name_not_present */
/* Do not encode anything */
break;
case 1: /* presentation_allowed */
if (name->char_set == 1) {
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
name->data, name->length));
} else {
ASN1_CALL(pos, rose_enc_qsig_NameSet(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 1, name));
}
break;
case 2: /* presentation_restricted */
if (name->char_set == 1) {
ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
name->data, name->length));
} else {
ASN1_CALL(pos, rose_enc_qsig_NameSet(ctrl, pos, end,
ASN1_CLASS_CONTEXT_SPECIFIC | 3, name));
}
break;
case 3: /* presentation_restricted_null */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 7));
break;
case 4: /* name_not_available */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown name presentation");
return NULL;
}
return pos;
}
/*!
* \internal
* \brief Encode the Q.SIG party-Name invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param party Information to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_PartyName_ARG_Backend(struct pri *ctrl,
unsigned char *pos, unsigned char *end, const struct roseQsigPartyName_ARG *party)
{
return rose_enc_qsig_Name(ctrl, pos, end, &party->name);
}
/*!
* \brief Encode the Q.SIG CallingName invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.CallingName);
}
/*!
* \brief Encode the Q.SIG CalledName invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.CalledName);
}
/*!
* \brief Encode the Q.SIG ConnectedName invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end,
&args->qsig.ConnectedName);
}
/*!
* \brief Encode the Q.SIG BusyName invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.BusyName);
}
/*!
* \internal
* \brief Decode the Q.SIG NameData Name argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param fname Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param name Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_NameData(struct pri *ctrl, const char *fname,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigName *name)
{
size_t str_len;
ASN1_CALL(pos, asn1_dec_string_bin(ctrl, fname, tag, pos, end, sizeof(name->data),
name->data, &str_len));
name->length = str_len;
return pos;
}
/*!
* \internal
* \brief Decode the Q.SIG NameSet Name argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param fname Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param name Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_NameSet(struct pri *ctrl, const char *fname,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigName *name)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s NameSet %s\n", fname, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING);
ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "nameData", tag, pos, seq_end, name));
if (pos < end && *pos != ASN1_INDEF_TERM) {
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "characterSet", tag, pos, seq_end, &value));
name->char_set = value;
} else {
name->char_set = 1; /* default to iso8859-1 */
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG Name argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param fname Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param name Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigName *name)
{
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s Name\n", fname);
}
name->char_set = 1; /* default to iso8859-1 */
switch (tag & ~ASN1_PC_MASK) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
name->presentation = 1; /* presentation_allowed */
ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "namePresentationAllowedSimple", tag,
pos, end, name));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
/* Must be constructed but we will not check for it for simplicity. */
name->presentation = 1; /* presentation_allowed */
ASN1_CALL(pos, rose_dec_qsig_NameSet(ctrl, "namePresentationAllowedExtended",
tag, pos, end, name));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
name->presentation = 2; /* presentation_restricted */
ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "namePresentationRestrictedSimple",
tag, pos, end, name));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
/* Must be constructed but we will not check for it for simplicity. */
name->presentation = 2; /* presentation_restricted */
ASN1_CALL(pos, rose_dec_qsig_NameSet(ctrl, "namePresentationRestrictedExtended",
tag, pos, end, name));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
/* Must not be constructed but we will not check for it for simplicity. */
name->presentation = 4; /* name_not_available */
name->length = 0;
name->data[0] = 0;
ASN1_CALL(pos, asn1_dec_null(ctrl, "nameNotAvailable", tag, pos, end));
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
/* Must not be constructed but we will not check for it for simplicity. */
name->presentation = 3; /* presentation_restricted_null */
name->length = 0;
name->data[0] = 0;
ASN1_CALL(pos, asn1_dec_null(ctrl, "namePresentationRestrictedNull", tag, pos,
end));
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
return pos;
}
/*!
* \internal
* \brief Decode the Q.SIG party-Name invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param name Field name
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param party Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_PartyName_ARG_Backend(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigPartyName_ARG *party)
{
int length;
int seq_offset;
const unsigned char *seq_end;
if (tag == ASN1_TAG_SEQUENCE) {
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "name", tag, pos, seq_end,
&party->name));
/* Fixup will skip over any OPTIONAL manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
} else {
ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, name, tag, pos, end, &party->name));
}
return pos;
}
/*!
* \brief Decode the Q.SIG CallingName invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "callingName", tag, pos, end,
&args->qsig.CallingName);
}
/*!
* \brief Decode the Q.SIG CalledName invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "calledName", tag, pos, end,
&args->qsig.CalledName);
}
/*!
* \brief Decode the Q.SIG ConnectedName invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "connectedName", tag, pos, end,
&args->qsig.ConnectedName);
}
/*!
* \brief Decode the Q.SIG BusyName invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "busyName", tag, pos, end,
&args->qsig.BusyName);
}
/* ------------------------------------------------------------------- */
/* end rose_qsig_name.c */

2473
rosetest.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,27 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@digium.com>
* Written by Mark Spencer <markster@linux-support.net>
*
* Copyright (C) 2001-2005, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
* All Rights Reserved.
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*
* This program tests libpri call reception using a zaptel interface.
* Its state machines are setup for RECEIVING CALLS ONLY, so if you
@@ -48,18 +42,15 @@
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <zaptel/zaptel.h>
#ifndef SOLARIS
#include <zap.h>
#if defined(__linux__)
#include <linux/zaptel.h>
#elif defined(__FreeBSD__)
#include <zaptel.h>
#endif
#include <zap.h>
#include <pthread.h>
#include <sys/select.h>
#include "libpri.h"
#include "pri_q931.h"
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#define DEBUG_LEVEL PRI_DEBUG_ALL
@@ -70,7 +61,7 @@ static struct pri *first, *cur;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#define TEST_CALLS 1
#define TEST_CALLS 32
static void event1(struct pri *pri, pri_event *e)
{
@@ -87,40 +78,14 @@ static void event1(struct pri *pri, pri_event *e)
sprintf(dest, "60%02d", x + 1);
if (!(calls[x] = pri_new_call(pri))) {
perror("pri_new_call");
continue;
}
#if 0
{
struct pri_sr *sr;
sr = pri_sr_new();
pri_sr_set_channel(sr, x+1, 0, 0);
pri_sr_set_bearer(sr, 0, PRI_LAYER_1_ULAW);
pri_sr_set_called(sr, dest, PRI_NATIONAL_ISDN, 1);
pri_sr_set_caller(sr, num, name, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN);
pri_sr_set_redirecting(sr, num, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
if (pri_setup(pri, calls[x], sr))
perror("pri_setup");
pri_sr_free(sr);
}
#else
if (pri_call(pri, calls[x], PRI_TRANS_CAP_DIGITAL, x + 1, 1, 1, num,
} else if (pri_call(pri, calls[x], PRI_TRANS_CAP_DIGITAL, x + 1, 1, 1, num,
PRI_NATIONAL_ISDN, name, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN,
dest, PRI_NATIONAL_ISDN, PRI_LAYER_1_ULAW)) {
perror("pri_call");
}
#endif
}
printf("Setup %d calls!\n", TEST_CALLS);
break;
case PRI_EVENT_RINGING:
printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
q931_facility(pri, e->ringing.call);
pri_answer(pri, e->ringing.call, e->ringing.channel, 0);
break;
case PRI_EVENT_HANGUP_REQ:
printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
pri_hangup(pri, e->hangup.call, e->hangup.cause);
break;
default:
printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
}
@@ -130,26 +95,13 @@ static void event2(struct pri *pri, pri_event *e)
{
/* CPE */
switch(e->gen.e) {
case PRI_EVENT_RING:
printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
pri_proceeding(pri, e->ring.call, e->ring.channel, 0);
pri_acknowledge(pri, e->ring.call, e->ring.channel, 0);
break;
case PRI_EVENT_ANSWER:
printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
pri_hangup(pri, e->answer.call, PRI_CAUSE_NORMAL_UNSPECIFIED);
break;
case PRI_EVENT_HANGUP:
printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
pri_hangup(pri, e->hangup.call, e->hangup.cause);
break;
case PRI_EVENT_DCHAN_UP:
default:
printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
}
}
static void testmsg(struct pri *pri, char *s)
static void testmsg(char *s)
{
char *c;
static int keeplast = 0;
@@ -175,7 +127,7 @@ static void testmsg(struct pri *pri, char *s)
keeplast = 0;
}
static void testerr(struct pri *pri, char *s)
static void testerr(char *s)
{
char *c;
static int keeplast = 0;
@@ -211,7 +163,7 @@ static void *dchan(void *data)
fd_set fds;
int res;
for(;;) {
if ((next = pri_schedule_next(pri))) {
if (next == pri_schedule_next(pri)) {
gettimeofday(&tv, NULL);
tv.tv_sec = next->tv_sec - tv.tv_sec;
tv.tv_usec = next->tv_usec - tv.tv_usec;
@@ -238,9 +190,9 @@ static void *dchan(void *data)
}
if (e) {
if (first == pri) {
event1(e->gen.pri, e);
event1(pri, e);
} else {
event2(e->gen.pri, e);
event2(pri, e);
}
}
pthread_mutex_unlock(&lock);
@@ -260,23 +212,21 @@ int main(int argc, char *argv[])
perror("socketpair");
exit(1);
}
if (!(pri = pri_new_bri(pair[0], 0, PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
if (!(pri = pri_new(pair[0], PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
perror("pri(0)");
exit(1);
}
first = pri;
pri_set_debug(pri, DEBUG_LEVEL);
pri_facility_enable(pri);
if (pthread_create(&tmp, NULL, dchan, pri)) {
perror("thread(0)");
exit(1);
}
if (!(pri = pri_new_bri(pair[1], 0, PRI_CPE, PRI_DEF_SWITCHTYPE))) {
if (!(pri = pri_new(pair[1], PRI_CPE, PRI_DEF_SWITCHTYPE))) {
perror("pri(1)");
exit(1);
}
pri_set_debug(pri, DEBUG_LEVEL);
pri_facility_enable(pri);
if (pthread_create(&tmp, NULL, dchan, pri)) {
perror("thread(1)");
exit(1);