ROSE ASN.1 facility encode and decode rewrite of existing messages.
Several components are now parsed correctly. Most notably: PartyNumber and Q.SIG Name. git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@766 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
18fa4716a5
commit
ba45095c5a
41
Makefile
41
Makefile
@ -41,8 +41,42 @@ SONAME:=1.4
|
||||
|
||||
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 version.o
|
||||
DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
|
||||
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_other.o \
|
||||
rose_q931.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_other.lo \
|
||||
rose_q931.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)
|
||||
INSTALL_PREFIX=$(DESTDIR)
|
||||
INSTALL_BASE=/usr
|
||||
@ -132,6 +166,9 @@ testprilib: testprilib.o
|
||||
pridump: pridump.o
|
||||
$(CC) -o pridump pridump.o -L. -lpri $(CFLAGS)
|
||||
|
||||
rosetest: rosetest.o
|
||||
$(CC) -o rosetest rosetest.o -L. -lpri $(CFLAGS)
|
||||
|
||||
MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
|
||||
|
||||
%.o: %.c
|
||||
|
257
asn1.h
Normal file
257
asn1.h
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 */
|
1281
asn1_primitive.c
Normal file
1281
asn1_primitive.c
Normal file
File diff suppressed because it is too large
Load Diff
70
libpri.h
70
libpri.h
@ -26,7 +26,14 @@
|
||||
* provided with that copy of Asterisk, instead of the license
|
||||
* terms granted here.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* All new global identifiers that are added to this file MUST be
|
||||
* prefixed with PRI_ or pri_ to indicate that they are part of this
|
||||
* library and to reduce potential naming conflicts.
|
||||
*/
|
||||
|
||||
#ifndef _LIBPRI_H
|
||||
#define _LIBPRI_H
|
||||
|
||||
@ -103,13 +110,13 @@
|
||||
#define PRI_PROG_CALLER_RETURNED_TO_ISDN (1 << 9)
|
||||
|
||||
/* Numbering plan identifier */
|
||||
#define PRI_NPI_UNKNOWN 0x0
|
||||
#define PRI_NPI_E163_E164 0x1
|
||||
#define PRI_NPI_X121 0x3
|
||||
#define PRI_NPI_F69 0x4
|
||||
#define PRI_NPI_NATIONAL 0x8
|
||||
#define PRI_NPI_PRIVATE 0x9
|
||||
#define PRI_NPI_RESERVED 0xF
|
||||
#define PRI_NPI_UNKNOWN 0x0 /*!< Unknown numbering plan */
|
||||
#define PRI_NPI_E163_E164 0x1 /*!< ISDN/telephony numbering plan (public) */
|
||||
#define PRI_NPI_X121 0x3 /*!< Data numbering plan */
|
||||
#define PRI_NPI_F69 0x4 /*!< Telex numbering plan */
|
||||
#define PRI_NPI_NATIONAL 0x8 /*!< National standard numbering plan */
|
||||
#define PRI_NPI_PRIVATE 0x9 /*!< Private numbering plan */
|
||||
#define PRI_NPI_RESERVED 0xF /*!< Reserved for extension */
|
||||
|
||||
/* Type of number */
|
||||
#define PRI_TON_UNKNOWN 0x0
|
||||
@ -137,15 +144,44 @@
|
||||
#define PRI_UNKNOWN 0x0
|
||||
|
||||
/* Presentation */
|
||||
#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
|
||||
#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
|
||||
#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
|
||||
#define PRES_ALLOWED_NETWORK_NUMBER 0x03
|
||||
#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
|
||||
#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
|
||||
#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
|
||||
#define PRES_PROHIB_NETWORK_NUMBER 0x23
|
||||
#define PRES_NUMBER_NOT_AVAILABLE 0x43
|
||||
#define PRI_PRES_NUMBER_TYPE 0x03
|
||||
#define PRI_PRES_USER_NUMBER_UNSCREENED 0x00
|
||||
#define PRI_PRES_USER_NUMBER_PASSED_SCREEN 0x01
|
||||
#define PRI_PRES_USER_NUMBER_FAILED_SCREEN 0x02
|
||||
#define PRI_PRES_NETWORK_NUMBER 0x03
|
||||
|
||||
#define PRI_PRES_RESTRICTION 0x60
|
||||
#define PRI_PRES_ALLOWED 0x00
|
||||
#define PRI_PRES_RESTRICTED 0x20
|
||||
#define PRI_PRES_UNAVAILABLE 0x40
|
||||
#define PRI_PRES_RESERVED 0x60
|
||||
|
||||
#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
|
||||
(PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED)
|
||||
|
||||
#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
|
||||
(PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
|
||||
|
||||
#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
|
||||
(PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
|
||||
|
||||
#define PRES_ALLOWED_NETWORK_NUMBER \
|
||||
(PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER)
|
||||
|
||||
#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
|
||||
(PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED)
|
||||
|
||||
#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
|
||||
(PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
|
||||
|
||||
#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
|
||||
(PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
|
||||
|
||||
#define PRES_PROHIB_NETWORK_NUMBER \
|
||||
(PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER)
|
||||
|
||||
#define PRES_NUMBER_NOT_AVAILABLE \
|
||||
(PRI_PRES_UNAVAILABLE | PRI_PRES_NETWORK_NUMBER)
|
||||
|
||||
/* Causes for disconnection */
|
||||
#define PRI_CAUSE_UNALLOCATED 1
|
||||
|
3872
pri_facility.c
3872
pri_facility.c
File diff suppressed because it is too large
Load Diff
257
pri_facility.h
257
pri_facility.h
@ -32,122 +32,13 @@
|
||||
#include "pri_q931.h"
|
||||
|
||||
/* 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
|
||||
|
||||
/* Argument values */
|
||||
#define ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE 0x80
|
||||
#define ROSE_NAME_PRESENTATION_RESTRICTED_NULL 0x87
|
||||
#define ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED 0xA1
|
||||
#define ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE 0xA2
|
||||
#define ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED 0xA3
|
||||
#define ROSE_NAME_NOT_AVAIL 0x84
|
||||
|
||||
/* Component types */
|
||||
#define COMP_TYPE_INTERPRETATION 0x8B
|
||||
#define COMP_TYPE_NETWORK_PROTOCOL_PROFILE 0x92
|
||||
#define COMP_TYPE_INVOKE 0xA1
|
||||
#define COMP_TYPE_RETURN_RESULT 0xA2
|
||||
#define COMP_TYPE_RETURN_ERROR 0xA3
|
||||
#define COMP_TYPE_REJECT 0xA4
|
||||
#define COMP_TYPE_NFE 0xAA
|
||||
|
||||
/* Operation ID values */
|
||||
/* Q.952.7 (ECMA-178) ROSE operations (Transfer) */
|
||||
#define ROSE_CALL_TRANSFER_IDENTIFY 7
|
||||
#define ROSE_CALL_TRANSFER_ABANDON 8
|
||||
#define ROSE_CALL_TRANSFER_INITIATE 9
|
||||
#define ROSE_CALL_TRANSFER_SETUP 10
|
||||
#define ROSE_CALL_TRANSFER_ACTIVE 11
|
||||
#define ROSE_CALL_TRANSFER_COMPLETE 12
|
||||
#define ROSE_CALL_TRANSFER_UPDATE 13
|
||||
#define ROSE_SUBADDRESS_TRANSFER 14
|
||||
/* Q.952 ROSE operations (Diverting) */
|
||||
#define ROSE_DIVERTING_LEG_INFORMATION1 18
|
||||
#define ROSE_DIVERTING_LEG_INFORMATION2 0x15
|
||||
#define ROSE_DIVERTING_LEG_INFORMATION3 19
|
||||
/* Q.956 ROSE operations (Advice Of Charge) */
|
||||
#define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26
|
||||
#define ROSE_AOC_CHARGING_REQUEST 30
|
||||
#define ROSE_AOC_AOCS_CURRENCY 31
|
||||
#define ROSE_AOC_AOCS_SPECIAL_ARR 32
|
||||
#define ROSE_AOC_AOCD_CURRENCY 33
|
||||
#define ROSE_AOC_AOCD_CHARGING_UNIT 34
|
||||
#define ROSE_AOC_AOCE_CURRENCY 35
|
||||
#define ROSE_AOC_AOCE_CHARGING_UNIT 36
|
||||
#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
|
||||
/* Q.SIG operations */
|
||||
#define SS_CNID_CALLINGNAME 0
|
||||
#define SS_ANFPR_PATHREPLACEMENT 4
|
||||
#define SS_DIVERTING_LEG_INFORMATION2 21
|
||||
#define SS_MWI_ACTIVATE 80
|
||||
#define SS_MWI_DEACTIVATE 81
|
||||
#define SS_MWI_INTERROGATE 82
|
||||
|
||||
/* ROSE definitions and data structures */
|
||||
#define INVOKE_IDENTIFIER 0x02
|
||||
#define INVOKE_LINKED_IDENTIFIER 0x80
|
||||
#define INVOKE_NULL_IDENTIFIER __USE_ASN1_NULL
|
||||
|
||||
/* ASN.1 Identifier Octet - Data types */
|
||||
#define ASN1_TYPE_MASK 0x1f
|
||||
#define ASN1_BOOLEAN 0x01
|
||||
#define ASN1_INTEGER 0x02
|
||||
#define ASN1_BITSTRING 0x03
|
||||
#define ASN1_OCTETSTRING 0x04
|
||||
#define ASN1_NULL 0x05
|
||||
#define ASN1_OBJECTIDENTIFIER 0x06
|
||||
#define ASN1_OBJECTDESCRIPTOR 0x07
|
||||
#define ASN1_EXTERN 0x08
|
||||
#define ASN1_REAL 0x09
|
||||
#define ASN1_ENUMERATED 0x0a
|
||||
#define ASN1_EMBEDDEDPDV 0x0b
|
||||
#define ASN1_UTF8STRING 0x0c
|
||||
#define ASN1_RELATIVEOBJECTID 0x0d
|
||||
/* 0x0e & 0x0f are reserved for future ASN.1 editions */
|
||||
#define ASN1_SEQUENCE 0x10
|
||||
#define ASN1_SET 0x11
|
||||
#define ASN1_NUMERICSTRING 0x12
|
||||
#define ASN1_PRINTABLESTRING 0x13
|
||||
#define ASN1_TELETEXSTRING 0x14
|
||||
#define ASN1_IA5STRING 0x16
|
||||
#define ASN1_UTCTIME 0x17
|
||||
#define ASN1_GENERALIZEDTIME 0x18
|
||||
|
||||
/* ASN.1 Identifier Octet - Tags */
|
||||
#define ASN1_TAG_0 0x00
|
||||
#define ASN1_TAG_1 0x01
|
||||
#define ASN1_TAG_2 0x02
|
||||
#define ASN1_TAG_3 0x03
|
||||
#define ASN1_TAG_4 0x04
|
||||
#define ASN1_TAG_5 0x05
|
||||
#define ASN1_TAG_6 0x06
|
||||
#define ASN1_TAG_7 0x07
|
||||
#define ASN1_TAG_8 0x08
|
||||
#define ASN1_TAG_9 0x09
|
||||
|
||||
/* ASN.1 Identifier Octet - Primitive/Constructor Bit */
|
||||
#define ASN1_PC_MASK 0x20
|
||||
#define ASN1_PRIMITIVE 0x00
|
||||
#define ASN1_CONSTRUCTOR 0x20
|
||||
|
||||
/* ASN.1 Identifier Octet - Clan Bits */
|
||||
#define ASN1_CLAN_MASK 0xc0
|
||||
#define ASN1_UNIVERSAL 0x00
|
||||
#define ASN1_APPLICATION 0x40
|
||||
#define ASN1_CONTEXT_SPECIFIC 0x80
|
||||
#define ASN1_PRIVATE 0xc0
|
||||
|
||||
/* ASN.1 Length masks */
|
||||
#define ASN1_LEN_INDEF 0x80
|
||||
|
||||
|
||||
#define INVOKE_OPERATION_INT __USE_ASN1_INTEGER
|
||||
#define INVOKE_OBJECT_ID __USE_ASN1_OBJECTIDENTIFIER
|
||||
|
||||
/* Q.952 Divert cause */
|
||||
#define Q952_DIVERT_REASON_UNKNOWN 0x00
|
||||
#define Q952_DIVERT_REASON_CFU 0x01
|
||||
@ -169,138 +60,6 @@
|
||||
#define Q932_TON_SUBSCRIBER 0x04
|
||||
#define Q932_TON_ABBREVIATED 0x06
|
||||
|
||||
/* RLT related Operations */
|
||||
#define RLT_SERVICE_ID 0x3e
|
||||
#define RLT_OPERATION_IND 0x01
|
||||
#define RLT_THIRD_PARTY 0x02
|
||||
|
||||
struct rose_component {
|
||||
u_int8_t type;
|
||||
u_int8_t len;
|
||||
u_int8_t data[0];
|
||||
};
|
||||
|
||||
#if 1
|
||||
#define GET_COMPONENT(component, idx, ptr, length) \
|
||||
if ((idx)+2 > (length)) \
|
||||
break; \
|
||||
(component) = (struct rose_component*)&((ptr)[idx]); \
|
||||
if ((idx)+(component)->len+2 > (length)) { \
|
||||
if ((component)->len != ASN1_LEN_INDEF) \
|
||||
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
|
||||
}
|
||||
#else /* Debugging */
|
||||
#define GET_COMPONENT(component, idx, ptr, length) \
|
||||
if ((idx)+2 > (length)) \
|
||||
break; \
|
||||
(component) = (struct rose_component*)&((ptr)[idx]); \
|
||||
if ((idx)+(component)->len+2 > (length)) { \
|
||||
if ((component)->len != 128) \
|
||||
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
|
||||
} \
|
||||
pri_message(pri, "XX %s:%d Got component %d (0x%02X), length %d\n", __FUNCTION__, __LINE__, (component)->type, (component)->type, (component)->len); \
|
||||
if ((component)->len > 0) { \
|
||||
int zzz; \
|
||||
pri_message(pri, "XX Data:"); \
|
||||
for (zzz = 0; zzz < (component)->len; ++zzz) \
|
||||
pri_message(pri, " %02X", (component)->data[zzz]); \
|
||||
pri_message(pri, "\n"); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NEXT_COMPONENT(component, idx) \
|
||||
(idx) += (component)->len + 2
|
||||
|
||||
#define SUB_COMPONENT(component, idx) \
|
||||
(idx) += 2
|
||||
|
||||
#define CHECK_COMPONENT(component, comptype, message) \
|
||||
if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
|
||||
pri_message(pri, (message), (component)->type); \
|
||||
asn1_dump(pri, (component), (component)->len+2); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define ASN1_GET_INTEGER(component, variable) \
|
||||
do { \
|
||||
int comp_idx; \
|
||||
(variable) = 0; \
|
||||
for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \
|
||||
(variable) = ((variable) << 8) | (component)->data[comp_idx]; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_FIXUP_LEN(component, size) \
|
||||
do { \
|
||||
if ((component)->len == ASN1_LEN_INDEF) \
|
||||
size += 2; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
|
||||
do { \
|
||||
(component) = (struct rose_component *)&((ptr)[(idx)]); \
|
||||
(component)->type = (comptype); \
|
||||
(component)->len = 0; \
|
||||
(idx) += 2; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \
|
||||
do { \
|
||||
(component) = (struct rose_component *)&((ptr)[(idx)]); \
|
||||
(component)->type = (comptype); \
|
||||
(component)->len = 1; \
|
||||
(component)->data[0] = (value); \
|
||||
(idx) += 3; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \
|
||||
do { \
|
||||
int __val = (value); \
|
||||
int __i = 0; \
|
||||
(component) = (struct rose_component *)&((ptr)[(idx)]); \
|
||||
(component)->type = (comptype); \
|
||||
if ((__val >> 24)) \
|
||||
(component)->data[__i++] = (__val >> 24) & 0xff; \
|
||||
if ((__val >> 16)) \
|
||||
(component)->data[__i++] = (__val >> 16) & 0xff; \
|
||||
if ((__val >> 8)) \
|
||||
(component)->data[__i++] = (__val >> 8) & 0xff; \
|
||||
(component)->data[__i++] = __val & 0xff; \
|
||||
(component)->len = __i; \
|
||||
(idx) += 2 + __i; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_PUSH(stack, stackpointer, component) \
|
||||
(stack)[(stackpointer)++] = (component)
|
||||
|
||||
#define ASN1_FIXUP(stack, stackpointer, data, idx) \
|
||||
do { \
|
||||
--(stackpointer); \
|
||||
(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
|
||||
} while (0)
|
||||
|
||||
/* Decoder for the invoke ROSE component */
|
||||
int rose_invoke_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||
|
||||
/* Decoder for the return result ROSE component */
|
||||
int rose_return_result_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||
|
||||
/* Decoder for the return error ROSE component */
|
||||
int rose_return_error_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||
|
||||
/* Decoder for the reject ROSE component */
|
||||
int rose_reject_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||
|
||||
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
|
||||
|
||||
int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
|
||||
|
||||
/* Get Name types from ASN.1 */
|
||||
int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
|
||||
|
||||
int typeofnumber_from_q931(struct pri *pri, int ton);
|
||||
|
||||
int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
|
||||
|
||||
/* 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);
|
||||
|
||||
@ -325,6 +84,18 @@ int pri_call_apdu_queue_cleanup(q931_call *call);
|
||||
/* Adds the "standard" APDUs to a call */
|
||||
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
|
||||
|
||||
int asn1_dump(struct pri *pri, void *comp, int len);
|
||||
void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1, const unsigned char *end);
|
||||
|
||||
/* Forward declare some ROSE structures for the following prototypes */
|
||||
struct fac_extension_header;
|
||||
struct rose_msg_invoke;
|
||||
struct rose_msg_result;
|
||||
struct rose_msg_error;
|
||||
struct rose_msg_reject;
|
||||
|
||||
void rose_handle_invoke(struct pri *ctrl, q931_call *call, 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, 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, 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, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
|
||||
|
||||
#endif /* _PRI_FACILITY_H */
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <stddef.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
#define DBGHEAD __FILE__ ":%d %s: "
|
||||
#define DBGINFO __LINE__,__PRETTY_FUNCTION__
|
||||
|
||||
@ -51,6 +53,7 @@ enum q931_mode;
|
||||
|
||||
#define MAX_TIMERS 32
|
||||
|
||||
/*! \brief D channel controller structure */
|
||||
struct pri {
|
||||
int fd; /* File descriptor for D-Channel */
|
||||
pri_io_cb read_func; /* Read data callback */
|
||||
@ -128,10 +131,11 @@ struct pri {
|
||||
unsigned int q931_rxcount;
|
||||
#endif
|
||||
|
||||
unsigned char last_invoke; /* Last ROSE invoke ID */
|
||||
short last_invoke; /* Last ROSE invoke ID */
|
||||
unsigned char sendfacility;
|
||||
};
|
||||
|
||||
/*! \brief New call setup parameter structure */
|
||||
struct pri_sr {
|
||||
int transmode;
|
||||
int channel;
|
||||
|
189
q931.c
189
q931.c
@ -33,6 +33,7 @@
|
||||
#include "pri_q921.h"
|
||||
#include "pri_q931.h"
|
||||
#include "pri_facility.h"
|
||||
#include "rose.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -1015,8 +1016,7 @@ static FUNC_DUMP(dump_redirecting_number)
|
||||
prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!(ie->data[i++]& 0x80));
|
||||
} while(!(ie->data[i++]& 0x80));
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
|
||||
pri_message(pri, " '%s' ]\n", cnum);
|
||||
}
|
||||
@ -1038,8 +1038,7 @@ static FUNC_DUMP(dump_connected_number)
|
||||
prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!(ie->data[i++]& 0x80));
|
||||
} while(!(ie->data[i++]& 0x80));
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
|
||||
pri_message(pri, " '%s' ]\n", cnum);
|
||||
}
|
||||
@ -1063,8 +1062,7 @@ static FUNC_RECV(receive_redirecting_number)
|
||||
call->redirectingreason = ie->data[i] & 0x0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!(ie->data[i++] & 0x80));
|
||||
} while(!(ie->data[i++] & 0x80));
|
||||
q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
|
||||
return 0;
|
||||
}
|
||||
@ -1353,15 +1351,19 @@ static FUNC_SEND(transmit_facility)
|
||||
if ((tmp->message == msgtype) && !tmp->sent)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tmp) /* No APDU found */
|
||||
return 0;
|
||||
|
||||
if (pri->debug & PRI_DEBUG_APDU) {
|
||||
pri_message(pri, "Adding facility ie contents to send message:\n");
|
||||
facility_decode_dump(pri, tmp->apdu, tmp->apdu_len);
|
||||
}
|
||||
|
||||
if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
|
||||
pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
|
||||
i += tmp->apdu_len;
|
||||
tmp->sent = 1;
|
||||
@ -1369,114 +1371,77 @@ static FUNC_SEND(transmit_facility)
|
||||
return i + 2;
|
||||
}
|
||||
|
||||
static FUNC_RECV(receive_facility)
|
||||
static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int protocol, next_protocol;
|
||||
struct rose_component *comp = NULL;
|
||||
enum {
|
||||
Q932_STATE_NFE, /* Network facility extension */
|
||||
Q932_STATE_NPP, /* Network protocol profile */
|
||||
Q932_STATE_INTERPRETATION, /* Interpretation component */
|
||||
Q932_STATE_SERVICE /* Service component(s) */
|
||||
} state = Q932_STATE_SERVICE;
|
||||
#define Q932_HANDLE_PROC(component, my_state, name, handler) \
|
||||
case component: \
|
||||
if(state > my_state) { \
|
||||
pri_error(pri, "!! %s component received in wrong place\n"); \
|
||||
break; \
|
||||
} \
|
||||
state = my_state; \
|
||||
if (pri->debug) \
|
||||
pri_message(pri, "Handle Q.932 %s component\n", name); \
|
||||
(handler)(pri, call, ie, comp->data, comp->len); \
|
||||
break;
|
||||
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
|
||||
case component: \
|
||||
if(state > my_state) { \
|
||||
pri_error(pri, "!! %s component received in wrong place\n"); \
|
||||
break; \
|
||||
} \
|
||||
state = my_state; \
|
||||
if (pri->debug & PRI_DEBUG_APDU) \
|
||||
pri_message(pri, "Q.932 %s component is not handled\n", name); \
|
||||
break;
|
||||
struct fac_extension_header header;
|
||||
struct rose_message rose;
|
||||
const unsigned char *pos;
|
||||
const unsigned char *end;
|
||||
|
||||
if (ie->len < 1)
|
||||
return -1;
|
||||
pos = ie->data;
|
||||
end = ie->data + ie->len;
|
||||
|
||||
switch(next_protocol = protocol = (ie->data[i] & 0x1f)) {
|
||||
case Q932_PROTOCOL_CMIP:
|
||||
case Q932_PROTOCOL_ACSE:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "!! Don't know how to handle Q.932 Protocol Profile of type 0x%X\n", protocol);
|
||||
/* Make sure we have enough room for the protocol profile ie octet(s) */
|
||||
if (end < pos + 2) {
|
||||
return -1;
|
||||
case Q932_PROTOCOL_EXTENSIONS:
|
||||
state = Q932_STATE_NFE;
|
||||
next_protocol = Q932_PROTOCOL_ROSE;
|
||||
break;
|
||||
}
|
||||
switch (*pos & Q932_PROTOCOL_MASK) {
|
||||
case Q932_PROTOCOL_ROSE:
|
||||
case Q932_PROTOCOL_EXTENSIONS:
|
||||
break;
|
||||
default:
|
||||
pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol);
|
||||
return -1;
|
||||
}
|
||||
/* Service indicator octet - Just ignore for now */
|
||||
if (!(ie->data[i] & 0x80))
|
||||
i++;
|
||||
i++;
|
||||
|
||||
if (ie->len < 3)
|
||||
return -1;
|
||||
|
||||
while ((i+1 < ie->len) && (&ie->data[i])) {
|
||||
comp = (struct rose_component*)&ie->data[i];
|
||||
if (comp->type) {
|
||||
if (protocol == Q932_PROTOCOL_EXTENSIONS) {
|
||||
switch (comp->type) {
|
||||
Q932_HANDLE_NULL(COMP_TYPE_INTERPRETATION, Q932_STATE_INTERPRETATION, "Interpretation", NULL);
|
||||
Q932_HANDLE_NULL(COMP_TYPE_NFE, Q932_STATE_NFE, "Network facility extensions", NULL);
|
||||
Q932_HANDLE_NULL(COMP_TYPE_NETWORK_PROTOCOL_PROFILE, Q932_STATE_NPP, "Network protocol profile", NULL);
|
||||
default:
|
||||
protocol = next_protocol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (protocol) {
|
||||
case Q932_PROTOCOL_ROSE:
|
||||
switch (comp->type) {
|
||||
Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
|
||||
Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode);
|
||||
Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode);
|
||||
Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode);
|
||||
default:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Q932_PROTOCOL_CMIP:
|
||||
switch (comp->type) {
|
||||
default:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "Don't know how to handle CMIP component of type 0x%X\n", comp->type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Q932_PROTOCOL_ACSE:
|
||||
switch (comp->type) {
|
||||
default:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "Don't know how to handle ACSE component of type 0x%X\n", comp->type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Q932_PROTOCOL_CMIP:
|
||||
case Q932_PROTOCOL_ACSE:
|
||||
if (ctrl->debug & PRI_DEBUG_APDU) {
|
||||
pri_message(ctrl,
|
||||
"!! Don't know how to handle Q.932 Protocol Profile type 0x%X\n",
|
||||
*pos & Q932_PROTOCOL_MASK);
|
||||
}
|
||||
i += (comp->len + 2);
|
||||
return -1;
|
||||
}
|
||||
#undef Q932_HANDLE
|
||||
if (!(*pos & 0x80)) {
|
||||
/* DMS-100 Service indicator octet - Just ignore for now */
|
||||
++pos;
|
||||
}
|
||||
++pos;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_APDU) {
|
||||
asn1_dump(ctrl, pos, end);
|
||||
}
|
||||
|
||||
pos = fac_dec_extension_header(ctrl, pos, end, &header);
|
||||
if (!pos) {
|
||||
return -1;
|
||||
}
|
||||
if (header.npp_present) {
|
||||
if (ctrl->debug & PRI_DEBUG_APDU) {
|
||||
pri_message(ctrl,
|
||||
"!! Don't know how to handle Network Protocol Profile type 0x%X\n",
|
||||
header.npp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = rose_decode(ctrl, pos, end, &rose);
|
||||
if (!pos) {
|
||||
return -1;
|
||||
}
|
||||
switch (rose.type) {
|
||||
case ROSE_COMP_TYPE_INVOKE:
|
||||
rose_handle_invoke(ctrl, call, ie, &header, &rose.component.invoke);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_RESULT:
|
||||
rose_handle_result(ctrl, call, ie, &header, &rose.component.result);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_ERROR:
|
||||
rose_handle_error(ctrl, call, ie, &header, &rose.component.error);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_REJECT:
|
||||
rose_handle_reject(ctrl, call, ie, &header, &rose.component.reject);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1711,12 +1676,13 @@ static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
|
||||
static FUNC_DUMP(dump_facility)
|
||||
{
|
||||
int dataat = (ie->data[0] & 0x80) ? 1 : 2;
|
||||
|
||||
pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
|
||||
dump_ie_data(pri, ie->data, ie->len);
|
||||
pri_message(NULL, " ]\n");
|
||||
if (ie->len > 1) {
|
||||
pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK);
|
||||
asn1_dump(pri, &ie->data[dataat], ie->len - dataat);
|
||||
pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & Q932_PROTOCOL_MASK);
|
||||
asn1_dump(pri, ie->data + dataat, ie->data + ie->len);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1725,7 +1691,7 @@ static FUNC_DUMP(dump_network_spec_fac)
|
||||
{
|
||||
pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
|
||||
if (ie->data[0] == 0x00) {
|
||||
pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
|
||||
pri_message(pri, "%s", code2str(ie->data[1], facilities, ARRAY_LEN(facilities)));
|
||||
}
|
||||
else
|
||||
dump_ie_data(pri, ie->data, ie->len);
|
||||
@ -2374,7 +2340,7 @@ static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char p
|
||||
|
||||
base_ie = (((full_ie & ~0x7f) == Q931_FULL_IE(0, 0x80)) && ((full_ie & 0x70) != 0x20)) ? full_ie & ~0x0f : full_ie;
|
||||
|
||||
for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++)
|
||||
for (x = 0; x < ARRAY_LEN(ies); ++x)
|
||||
if (ies[x].ie == base_ie) {
|
||||
if (ies[x].dump)
|
||||
ies[x].dump(full_ie, pri, ie, ielen(ie), prefix);
|
||||
@ -2534,8 +2500,7 @@ static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie
|
||||
maxlen -= res;
|
||||
iet = (q931_ie *)((char *)iet + res);
|
||||
}
|
||||
}
|
||||
while (res > 0 && order < ies_count);
|
||||
} while (res > 0 && order < ies_count);
|
||||
if (have_shift && total_res) {
|
||||
if (Q931_IE_CODESET(ies[x].ie))
|
||||
*codeset = Q931_IE_CODESET(ies[x].ie);
|
||||
|
983
rose_address.c
Normal file
983
rose_address.c
Normal file
@ -0,0 +1,983 @@
|
||||
/*
|
||||
* 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 */
|
1929
rose_etsi_aoc.c
Normal file
1929
rose_etsi_aoc.c
Normal file
File diff suppressed because it is too large
Load Diff
332
rose_internal.h
Normal file
332
rose_internal.h
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* 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:
|
||||
* 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 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 */
|
277
rose_other.c
Normal file
277
rose_other.c
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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 */
|
100
rose_q931.c
Normal file
100
rose_q931.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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 */
|
883
rose_qsig_ct.c
Normal file
883
rose_qsig_ct.c
Normal file
@ -0,0 +1,883 @@
|
||||
/*
|
||||
* 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 */
|
1390
rose_qsig_diversion.c
Normal file
1390
rose_qsig_diversion.c
Normal file
File diff suppressed because it is too large
Load Diff
790
rose_qsig_mwi.c
Normal file
790
rose_qsig_mwi.c
Normal file
@ -0,0 +1,790 @@
|
||||
/*
|
||||
* 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 */
|
474
rose_qsig_name.c
Normal file
474
rose_qsig_name.c
Normal file
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* 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 */
|
1713
rosetest.c
Normal file
1713
rosetest.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user