aboutsummaryrefslogtreecommitdiffstats
path: root/main/libpri
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2011-07-07 16:14:24 +0300
committerTimo Teräs <timo.teras@iki.fi>2011-07-07 16:14:24 +0300
commit491adc1d879b67ff4095fd32eb376f9e580e97ad (patch)
tree45caf5b64a48186352e8fe7e502c9c9bd296750f /main/libpri
parent05a00bd3b1689298d2ad59c797d43424c18ea855 (diff)
downloadaports-491adc1d879b67ff4095fd32eb376f9e580e97ad.tar.bz2
aports-491adc1d879b67ff4095fd32eb376f9e580e97ad.tar.xz
main/libpri: upgrade to 1.4.12
* remove unneeded patches
Diffstat (limited to 'main/libpri')
-rw-r--r--main/libpri/APKBUILD7
-rw-r--r--main/libpri/libpri-1.4-r1357.patch39961
-rw-r--r--main/libpri/libpri-cflags.patch21
3 files changed, 4 insertions, 39985 deletions
diff --git a/main/libpri/APKBUILD b/main/libpri/APKBUILD
index aec4f46831..fef96994fe 100644
--- a/main/libpri/APKBUILD
+++ b/main/libpri/APKBUILD
@@ -1,8 +1,8 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=libpri
-pkgver=1.4.12_beta3
-_pkgver=1.4.12-beta3
+pkgver=1.4.12
+_pkgver=$pkgver
pkgrel=0
pkgdesc="Primary Rate ISDN (PRI) library"
url="http://www.asterisk.orig"
@@ -30,4 +30,5 @@ package() {
make LDCONFIG="echo" INSTALL_PREFIX="$pkgdir" install
}
-md5sums="9cbbaa009264b76af930529e8aae8cfd libpri-1.4.12-beta3.tar.gz"
+md5sums="9de39b866f049cc20a4f431cc6245166 libpri-1.4.12.tar.gz
+8df2ca48ce7db4f1a8604b0904bc9394 libpri-cflags.patch"
diff --git a/main/libpri/libpri-1.4-r1357.patch b/main/libpri/libpri-1.4-r1357.patch
deleted file mode 100644
index be827eebb7..0000000000
--- a/main/libpri/libpri-1.4-r1357.patch
+++ /dev/null
@@ -1,39961 +0,0 @@
-===================================================================
---- a/pri_timers.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_timers.h (.../branches/1.4) (revision 1357)
-@@ -1,97 +0,0 @@
--/*
-- * libpri: An implementation of Primary Rate ISDN
-- *
-- * Written by Mark Spencer <markster@digium.com>
-- *
-- * Copyright (C) 2001, Digium, Inc.
-- * All Rights Reserved.
-- */
--
--/*
-- * See http://www.asterisk.org for more information about
-- * the Asterisk project. Please do not directly contact
-- * any of the maintainers of this project for assistance;
-- * the project provides a web site, mailing lists and IRC
-- * channels for your use.
-- *
-- * This program is free software, distributed under the terms of
-- * the GNU General Public License Version 2 as published by the
-- * Free Software Foundation. See the LICENSE file included with
-- * this program for more details.
-- *
-- * In addition, when this program is distributed with Asterisk in
-- * any form that would qualify as a 'combined work' or as a
-- * 'derivative work' (but not mere aggregation), you can redistribute
-- * and/or modify the combination under the terms of the license
-- * provided with that copy of Asterisk, instead of the license
-- * terms granted here.
-- */
--
--#ifndef _PRI_TIMERS_H
--#define _PRI_TIMERS_H
--
--/* -1 means we dont currently support the timer/counter */
--#define PRI_TIMERS_DEFAULT { \
-- 3, /* N200 */ \
-- -1, /* N201 */ \
-- 3, /* N202 */ \
-- 7, /* K */ \
-- 1000, /* T200 */ \
-- -1, /* T201 */ \
-- 10000, /* T202 */ \
-- 10000, /* T203 */ \
-- -1, /* T300 */ \
-- -1, /* T301 */ \
-- -1, /* T302 */ \
-- -1, /* T303 */ \
-- -1, /* T304 */ \
-- 30000, /* T305 */ \
-- -1, /* T306 */ \
-- -1, /* T307 */ \
-- 4000, /* T308 */ \
-- -1, /* T309 */ \
-- -1, /* T310 */ \
-- 4000, /* T313 */ \
-- -1, /* T314 */ \
-- -1, /* T316 */ \
-- -1, /* T317 */ \
-- -1, /* T318 */ \
-- -1, /* T319 */ \
-- -1, /* T320 */ \
-- -1, /* T321 */ \
-- -1, /* T322 */ \
-- 2500, /* TM20 - Q.921 Appendix IV */ \
-- 3, /* NM20 - Q.921 Appendix IV */ \
-- }
--
--/* XXX Only our default timers are setup now XXX */
--#define PRI_TIMERS_UNKNOWN PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_NI2 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_DMS100 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_LUCENT5E PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_ATT4ESS PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_EUROISDN_E1 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_EUROISDN_T1 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_NI1 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_GR303_EOC PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_GR303_TMC PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_QSIG PRI_TIMERS_DEFAULT
--#define __PRI_TIMERS_GR303_EOC_INT PRI_TIMERS_DEFAULT
--#define __PRI_TIMERS_GR303_TMC_INT PRI_TIMERS_DEFAULT
--
--#define PRI_TIMERS_ALL { PRI_TIMERS_UNKNOWN, \
-- PRI_TIMERS_NI2, \
-- PRI_TIMERS_DMS100, \
-- PRI_TIMERS_LUCENT5E, \
-- PRI_TIMERS_ATT4ESS, \
-- PRI_TIMERS_EUROISDN_E1, \
-- PRI_TIMERS_EUROISDN_T1, \
-- PRI_TIMERS_NI1, \
-- PRI_TIMERS_QSIG, \
-- PRI_TIMERS_GR303_EOC, \
-- PRI_TIMERS_GR303_TMC, \
-- __PRI_TIMERS_GR303_EOC_INT, \
-- __PRI_TIMERS_GR303_TMC_INT, \
-- }
--
--#endif
-Index: .version
-===================================================================
---- a/.version (.../tags/1.4.10.2) (revision 1357)
-+++ b/.version (.../branches/1.4) (revision 1357)
-@@ -1 +1 @@
--1.4.10.2
-+1.4.10.2-r1357
-Index: prisched.c
-===================================================================
---- a/prisched.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/prisched.c (.../branches/1.4) (revision 1357)
-@@ -33,25 +33,43 @@
- #include "pri_internal.h"
-
-
-+/*! \brief The maximum number of timers that were active at once. */
- static int maxsched = 0;
-
- /* Scheduler routines */
--int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data)
-+
-+/*!
-+ * \brief Start a timer to schedule an event.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param ms Number of milliseconds to scheduled event.
-+ * \param function Callback function to call when timeout.
-+ * \param data Value to give callback function when timeout.
-+ *
-+ * \retval 0 if scheduler table is full and could not schedule the event.
-+ * \retval id Scheduled event id.
-+ */
-+int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
- {
- int x;
- struct timeval tv;
-+
- /* Scheduling runs on master channels only */
-- while (pri->master)
-- pri = pri->master;
-- for (x=1;x<MAX_SCHED;x++)
-- if (!pri->pri_sched[x].callback)
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
-+ }
-+ for (x = 0; x < MAX_SCHED; ++x) {
-+ if (!ctrl->pri_sched[x].callback) {
- break;
-+ }
-+ }
- if (x == MAX_SCHED) {
-- pri_error(pri, "No more room in scheduler\n");
-- return -1;
-+ pri_error(ctrl, "No more room in scheduler\n");
-+ return 0;
- }
-- if (x > maxsched)
-- maxsched = x;
-+ if (x >= maxsched) {
-+ maxsched = x + 1;
-+ }
- gettimeofday(&tv, NULL);
- tv.tv_sec += ms / 1000;
- tv.tv_usec += (ms % 1000) * 1000;
-@@ -59,71 +77,110 @@
- tv.tv_usec -= 1000000;
- tv.tv_sec += 1;
- }
-- pri->pri_sched[x].when = tv;
-- pri->pri_sched[x].callback = function;
-- pri->pri_sched[x].data = data;
-- return x;
-+ ctrl->pri_sched[x].when = tv;
-+ ctrl->pri_sched[x].callback = function;
-+ ctrl->pri_sched[x].data = data;
-+ return x + 1;
- }
-
--struct timeval *pri_schedule_next(struct pri *pri)
-+/*!
-+ * \brief Determine the time of the next scheduled event to expire.
-+ *
-+ * \param ctrl D channel controller.
-+ *
-+ * \return Time of the next scheduled event to expire or NULL if no timers active.
-+ */
-+struct timeval *pri_schedule_next(struct pri *ctrl)
- {
- struct timeval *closest = NULL;
- int x;
-- /* Check subchannels */
-- if (pri->subchannel)
-- closest = pri_schedule_next(pri->subchannel);
-- for (x=1;x<MAX_SCHED;x++) {
-- if (pri->pri_sched[x].callback &&
-- (!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
-- ((closest->tv_sec == pri->pri_sched[x].when.tv_sec) &&
-- (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
-- closest = &pri->pri_sched[x].when;
-+
-+ /* Scheduling runs on master channels only */
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
- }
-+ for (x = 0; x < MAX_SCHED; ++x) {
-+ if (ctrl->pri_sched[x].callback && (!closest
-+ || (closest->tv_sec > ctrl->pri_sched[x].when.tv_sec)
-+ || ((closest->tv_sec == ctrl->pri_sched[x].when.tv_sec)
-+ && (closest->tv_usec > ctrl->pri_sched[x].when.tv_usec)))) {
-+ closest = &ctrl->pri_sched[x].when;
-+ }
-+ }
- return closest;
- }
-
--static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
-+/*!
-+ * \internal
-+ * \brief Run all expired timers or return an event generated by an expired timer.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param tv Current time.
-+ *
-+ * \return Event for upper layer to process or NULL if all expired timers run.
-+ */
-+static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
- {
- int x;
- void (*callback)(void *);
- void *data;
-- pri_event *e;
-- if (pri->subchannel) {
-- if ((e = __pri_schedule_run(pri->subchannel, tv))) {
-- return e;
-+
-+ /* Scheduling runs on master channels only */
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
-+ }
-+ for (x = 0; x < MAX_SCHED; ++x) {
-+ if (ctrl->pri_sched[x].callback && ((ctrl->pri_sched[x].when.tv_sec < tv->tv_sec)
-+ || ((ctrl->pri_sched[x].when.tv_sec == tv->tv_sec)
-+ && (ctrl->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
-+ /* This timer has expired. */
-+ ctrl->schedev = 0;
-+ callback = ctrl->pri_sched[x].callback;
-+ data = ctrl->pri_sched[x].data;
-+ ctrl->pri_sched[x].callback = NULL;
-+ callback(data);
-+ if (ctrl->schedev) {
-+ return &ctrl->ev;
-+ }
- }
- }
-- for (x=1;x<MAX_SCHED;x++) {
-- if (pri->pri_sched[x].callback &&
-- ((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
-- ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
-- (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
-- pri->schedev = 0;
-- callback = pri->pri_sched[x].callback;
-- data = pri->pri_sched[x].data;
-- pri->pri_sched[x].callback = NULL;
-- pri->pri_sched[x].data = NULL;
-- callback(data);
-- if (pri->schedev)
-- return &pri->ev;
-- }
-- }
- return NULL;
- }
-
--pri_event *pri_schedule_run(struct pri *pri)
-+/*!
-+ * \brief Run all expired timers or return an event generated by an expired timer.
-+ *
-+ * \param ctrl D channel controller.
-+ *
-+ * \return Event for upper layer to process or NULL if all expired timers run.
-+ */
-+pri_event *pri_schedule_run(struct pri *ctrl)
- {
- struct timeval tv;
-+
- gettimeofday(&tv, NULL);
-- return __pri_schedule_run(pri, &tv);
-+ return __pri_schedule_run(ctrl, &tv);
- }
-
--
--void pri_schedule_del(struct pri *pri,int id)
-+/*!
-+ * \brief Delete a scheduled event.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param id Scheduled event id to delete.
-+ * 0 is a disabled/unscheduled event id that is ignored.
-+ * 1 - MAX_SCHED is a valid event id.
-+ *
-+ * \return Nothing
-+ */
-+void pri_schedule_del(struct pri *ctrl, int id)
- {
-- while (pri->master)
-- pri = pri->master;
-- if ((id >= MAX_SCHED) || (id < 0))
-- pri_error(pri, "Asked to delete sched id %d???\n", id);
-- pri->pri_sched[id].callback = NULL;
-+ /* Scheduling runs on master channels only */
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
-+ }
-+ if (0 < id && id <= MAX_SCHED) {
-+ ctrl->pri_sched[id - 1].callback = NULL;
-+ } else if (id) {
-+ pri_error(ctrl, "Asked to delete sched id %d???\n", id);
-+ }
- }
-Index: rose_qsig_mwi.c
-===================================================================
---- a/rose_qsig_mwi.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_qsig_mwi.c (.../branches/1.4) (revision 1357)
-@@ -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 */
-
-Property changes on: rose_qsig_mwi.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rosetest.c
-===================================================================
---- a/rosetest.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rosetest.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,2473 @@
-+/*
-+ * 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 encode/decode test program
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+static const struct fac_extension_header fac_headers[] = {
-+/* *INDENT-OFF* */
-+ {
-+ .nfe_present = 0,
-+ },
-+ {
-+ .nfe_present = 1,
-+ .nfe.source_entity = 1,
-+ .nfe.destination_entity = 1,
-+ },
-+ {
-+ .nfe_present = 1,
-+ .nfe.source_entity = 1,
-+ .nfe.source_number.plan = 4,
-+ .nfe.source_number.length = 4,
-+ .nfe.source_number.str = "9834",
-+ .nfe.destination_entity = 1,
-+ .nfe.destination_number.plan = 4,
-+ .nfe.destination_number.length = 4,
-+ .nfe.destination_number.str = "9834",
-+ },
-+ {
-+ .nfe_present = 1,
-+ .nfe.source_entity = 1,
-+ .nfe.destination_entity = 1,
-+ .npp_present = 1,
-+ .npp = 19,
-+ .interpretation_present = 1,
-+ .interpretation = 2,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_etsi_msgs[] = {
-+/* *INDENT-OFF* */
-+ /* Error messages */
-+ {
-+ .type = ROSE_COMP_TYPE_ERROR,
-+ .component.error.invoke_id = 82,
-+ .component.error.code = ROSE_ERROR_Div_SpecialServiceNr,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_ERROR,
-+ .component.error.invoke_id = 8,
-+ .component.error.code = ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
-+ },
-+
-+ /* Reject messages */
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.code = ROSE_REJECT_Gen_BadlyStructuredComponent,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.invoke_id_present = 1,
-+ .component.reject.invoke_id = 10,
-+ .component.reject.code = ROSE_REJECT_Inv_InitiatorReleasing,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.invoke_id_present = 1,
-+ .component.reject.invoke_id = 11,
-+ .component.reject.code = ROSE_REJECT_Res_MistypedResult,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.invoke_id_present = 1,
-+ .component.reject.invoke_id = 12,
-+ .component.reject.code = ROSE_REJECT_Err_ErrorResponseUnexpected,
-+ },
-+
-+ /* Anonymous result or result without any arguments. */
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_None,
-+ .component.result.invoke_id = 9,
-+ },
-+
-+ /* Advice Of Charge (AOC) */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ChargingRequest,
-+ .component.invoke.invoke_id = 98,
-+ .component.invoke.args.etsi.ChargingRequest.charging_case = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 99,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.special_charging_code = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 100,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.length = 8,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.scale = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 101,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.length = 8,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.scale = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity_present = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity.length = 20,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity.scale = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 102,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 2,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 103,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 3,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.currency = "Yen",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.amount.currency = 300,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.amount.multiplier = 5,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 104,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 2,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 2,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].currency_type = 3,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.currency = "Yen",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.amount.currency = 300,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.amount.multiplier = 5,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 105,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 106,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 5,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSCurrency,
-+ .component.invoke.invoke_id = 107,
-+ .component.invoke.args.etsi.AOCSCurrency.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSCurrency,
-+ .component.invoke.invoke_id = 108,
-+ .component.invoke.args.etsi.AOCSCurrency.type = 1,
-+ .component.invoke.args.etsi.AOCSCurrency.currency_info.num_records = 1,
-+ .component.invoke.args.etsi.AOCSCurrency.currency_info.list[0].charged_item = 3,
-+ .component.invoke.args.etsi.AOCSCurrency.currency_info.list[0].currency_type = 4,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSSpecialArr,
-+ .component.invoke.invoke_id = 109,
-+ .component.invoke.args.etsi.AOCSSpecialArr.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSSpecialArr,
-+ .component.invoke.invoke_id = 110,
-+ .component.invoke.args.etsi.AOCSSpecialArr.type = 1,
-+ .component.invoke.args.etsi.AOCSSpecialArr.special_arrangement = 9,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 111,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 112,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 113,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 2,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 114,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 2,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.type_of_charging_info = 1,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.billing_id = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 115,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 116,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 117,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 118,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 0,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].number_of_units = 8523,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 119,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit = 13,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 120,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 0,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].number_of_units = 8523,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit = 13,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 121,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].not_available = 0,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].number_of_units = 8523,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].type_of_unit_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].type_of_unit = 13,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 122,
-+ .component.invoke.args.etsi.AOCECurrency.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 123,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 124,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 125,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.plan = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.length = 7,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.str = "5551212",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 126,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 127,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 128,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 129,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id = 2,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 130,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 131,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 132,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 133,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 134,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 135,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 136,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id = 2,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
-+ },
-+
-+ /* Call diversion */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ActivationDiversion,
-+ .component.invoke.invoke_id = 67,
-+ .component.invoke.linked_id_present = 1,
-+ .component.invoke.linked_id = 27,
-+ .component.invoke.args.etsi.ActivationDiversion.procedure = 2,
-+ .component.invoke.args.etsi.ActivationDiversion.basic_service = 3,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.plan = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.length = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.str = "1803",
-+ .component.invoke.args.etsi.ActivationDiversion.served_user_number.plan = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.served_user_number.length = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.served_user_number.str = "5398",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ActivationDiversion,
-+ .component.invoke.invoke_id = 68,
-+ .component.invoke.args.etsi.ActivationDiversion.procedure = 1,
-+ .component.invoke.args.etsi.ActivationDiversion.basic_service = 5,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.plan = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.length = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ActivationDiversion,
-+ .component.result.invoke_id = 69,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DeactivationDiversion,
-+ .component.invoke.invoke_id = 70,
-+ .component.invoke.args.etsi.DeactivationDiversion.procedure = 1,
-+ .component.invoke.args.etsi.DeactivationDiversion.basic_service = 5,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_DeactivationDiversion,
-+ .component.result.invoke_id = 71,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ActivationStatusNotificationDiv,
-+ .component.invoke.invoke_id = 72,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.procedure = 1,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.basic_service = 5,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.plan = 4,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.length = 4,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DeactivationStatusNotificationDiv,
-+ .component.invoke.invoke_id = 73,
-+ .component.invoke.args.etsi.DeactivationStatusNotificationDiv.procedure = 1,
-+ .component.invoke.args.etsi.DeactivationStatusNotificationDiv.basic_service = 5,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_InterrogationDiversion,
-+ .component.invoke.invoke_id = 74,
-+ .component.invoke.args.etsi.InterrogationDiversion.procedure = 1,
-+ .component.invoke.args.etsi.InterrogationDiversion.basic_service = 5,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_InterrogationDiversion,
-+ .component.invoke.invoke_id = 75,
-+ .component.invoke.args.etsi.InterrogationDiversion.procedure = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_InterrogationDiversion,
-+ .component.result.invoke_id = 76,
-+ .component.result.args.etsi.InterrogationDiversion.num_records = 2,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].procedure = 2,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].basic_service = 5,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.plan = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.length = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.str = "1803",
-+ .component.result.args.etsi.InterrogationDiversion.list[1].procedure = 1,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].basic_service = 3,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.plan = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.length = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.str = "1903",
-+ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.plan = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.length = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.str = "5398",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 77,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
-+ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.type = 1,
-+ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.length = 4,
-+ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.u.nsap = "6492",
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 0,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.screening_indicator = 3,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.plan = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.length = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.str = "1803",
-+ .component.invoke.args.etsi.DiversionInformation.original_called_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.original_called.presentation = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting.presentation = 2,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_reason_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie.length = 5,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie_contents = "79828",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 78,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 1,
-+ .component.invoke.args.etsi.DiversionInformation.original_called_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.original_called.presentation = 2,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 79,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 3,
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 80,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 3,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.screening_indicator = 2,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.plan = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.length = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 81,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 4,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie.length = 5,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie_contents = "79828",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 82,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 4,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallDeflection,
-+ .component.invoke.invoke_id = 83,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1,
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallDeflection,
-+ .component.invoke.invoke_id = 84,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1,
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallDeflection,
-+ .component.invoke.invoke_id = 85,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_CallDeflection,
-+ .component.result.invoke_id = 86,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallRerouting,
-+ .component.invoke.invoke_id = 87,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
-+ .component.invoke.args.etsi.CallRerouting.q931ie.length = 129,
-+ .component.invoke.args.etsi.CallRerouting.q931ie_contents =
-+ "YEHAW."
-+ " The quick brown fox jumped over the lazy dog test."
-+ " Now is the time for all good men to come to the aid of their country.",
-+ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.etsi.CallRerouting.subscription_option = 2,
-+ .component.invoke.args.etsi.CallRerouting.calling_subaddress.type = 1,
-+ .component.invoke.args.etsi.CallRerouting.calling_subaddress.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.calling_subaddress.u.nsap = "6492",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallRerouting,
-+ .component.invoke.invoke_id = 88,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
-+ .component.invoke.args.etsi.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.etsi.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.etsi.CallRerouting.subscription_option = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallRerouting,
-+ .component.invoke.invoke_id = 89,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
-+ .component.invoke.args.etsi.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.etsi.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_CallRerouting,
-+ .component.result.invoke_id = 90,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_InterrogateServedUserNumbers,
-+ .component.invoke.invoke_id = 91,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_InterrogateServedUserNumbers,
-+ .component.result.invoke_id = 92,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.num_records = 2,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].plan = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].length = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].str = "1803",
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].plan = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].length = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].str = "5786",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation1,
-+ .component.invoke.invoke_id = 93,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diversion_reason = 4,
-+ .component.invoke.args.etsi.DivertingLegInformation1.subscription_option = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diverted_to_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diverted_to.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation1,
-+ .component.invoke.invoke_id = 94,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diversion_reason = 4,
-+ .component.invoke.args.etsi.DivertingLegInformation1.subscription_option = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 95,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 3,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diverting_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diverting.presentation = 2,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 96,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 3,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 97,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation3,
-+ .component.invoke.invoke_id = 98,
-+ .component.invoke.args.etsi.DivertingLegInformation3.presentation_allowed_indicator = 1,
-+ },
-+
-+ /* Explicit Call Transfer (ECT) */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctExecute,
-+ .component.invoke.invoke_id = 54,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ExplicitEctExecute,
-+ .component.invoke.invoke_id = 55,
-+ .component.invoke.args.etsi.ExplicitEctExecute.link_id = 23,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_RequestSubaddress,
-+ .component.invoke.invoke_id = 56,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_SubaddressTransfer,
-+ .component.invoke.invoke_id = 57,
-+ .component.invoke.args.etsi.SubaddressTransfer.subaddress.type = 1,
-+ .component.invoke.args.etsi.SubaddressTransfer.subaddress.length = 4,
-+ .component.invoke.args.etsi.SubaddressTransfer.subaddress.u.nsap = "6492",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctLinkIdRequest,
-+ .component.invoke.invoke_id = 58,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_EctLinkIdRequest,
-+ .component.result.invoke_id = 59,
-+ .component.result.args.etsi.EctLinkIdRequest.link_id = 76,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 60,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 0,
-+ .component.invoke.args.etsi.EctInform.redirection.number.plan = 8,
-+ .component.invoke.args.etsi.EctInform.redirection.number.length = 4,
-+ .component.invoke.args.etsi.EctInform.redirection.number.str = "6229",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 61,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 62,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 63,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 3,
-+ .component.invoke.args.etsi.EctInform.redirection.number.plan = 8,
-+ .component.invoke.args.etsi.EctInform.redirection.number.length = 4,
-+ .component.invoke.args.etsi.EctInform.redirection.number.str = "3340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 64,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 0,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctLoopTest,
-+ .component.invoke.invoke_id = 65,
-+ .component.invoke.args.etsi.EctLoopTest.call_transfer_id = 7,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_EctLoopTest,
-+ .component.result.invoke_id = 66,
-+ .component.result.args.etsi.EctLoopTest.loop_result = 2,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_indefinite_len[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <80>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <07>
-+ * Sequence/C(48 0x30) <30> Len:16 <80>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <80>
-+ * Context Specific [4 0x04] <84> Len:4 <80>
-+ * <31 38 30 33>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00,
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00
-+ */
-+ 0x91,
-+ 0xA1, 0x80,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x07,
-+ 0x30, 0x80,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x80,
-+ 0x84, 0x80,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x05, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_unused_indefinite_len[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <80>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <06> -- EctExecute
-+ * Sequence/C(48 0x30) <30> Len:16 <80>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <80>
-+ * Context Specific [4 0x04] <84> Len:4 <80>
-+ * <31 38 30 33>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00,
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00
-+ */
-+ 0x91,
-+ 0xA1, 0x80,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x06,
-+ 0x30, 0x80,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x80,
-+ 0x84, 0x80,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x05, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_unused[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <18>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <06> -- EctExecute
-+ * Sequence/C(48 0x30) <30> Len:16 <10>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <06>
-+ * Context Specific [4 0x04] <84> Len:4 <04>
-+ * <31 38 30 33>
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ */
-+ 0x91,
-+ 0xA1, 0x18,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x06,
-+ 0x30, 0x10,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x06,
-+ 0x84, 0x04,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x05, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_extra[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <18>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <07>
-+ * Sequence/C(48 0x30) <30> Len:16 <10>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <06>
-+ * Context Specific [4 0x04] <84> Len:4 <04>
-+ * <31 38 30 33>
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ */
-+ 0x91,
-+ 0xA1, 0x18,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x07,
-+ 0x30, 0x10,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x06,
-+ 0x84, 0x04,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x05, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_qsig_msgs[] = {
-+/* *INDENT-OFF* */
-+ /* Q.SIG Name-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 2,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 1,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 3,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 1,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 3,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 4,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 2,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 5,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 2,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 3,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 6,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 3,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 7,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CalledName,
-+ .component.invoke.invoke_id = 8,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ConnectedName,
-+ .component.invoke.invoke_id = 9,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_BusyName,
-+ .component.invoke.invoke_id = 10,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+
-+ /* Q.SIG SS-AOC-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
-+ .component.invoke.invoke_id = 11,
-+ .component.invoke.args.qsig.ChargeRequest.num_records = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
-+ .component.invoke.invoke_id = 12,
-+ .component.invoke.args.qsig.ChargeRequest.num_records = 1,
-+ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[0] = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
-+ .component.invoke.invoke_id = 13,
-+ .component.invoke.args.qsig.ChargeRequest.num_records = 2,
-+ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[0] = 4,
-+ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[1] = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_ChargeRequest,
-+ .component.result.invoke_id = 14,
-+ .component.result.args.qsig.ChargeRequest.advice_mode_combination = 3,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_GetFinalCharge,
-+ .component.invoke.invoke_id = 15,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 16,
-+ .component.invoke.args.qsig.AocFinal.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 17,
-+ .component.invoke.args.qsig.AocFinal.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 18,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 19,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id_present = 1,
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 20,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocFinal.charging_association.id = 200,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 21,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id_present = 1,
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id = 2,
-+ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocFinal.charging_association.id = 200,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 22,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.type = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.number.plan = 4,
-+ .component.invoke.args.qsig.AocFinal.charging_association.number.length = 4,
-+ .component.invoke.args.qsig.AocFinal.charging_association.number.str = "1802",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 23,
-+ .component.invoke.args.qsig.AocInterim.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 24,
-+ .component.invoke.args.qsig.AocInterim.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 25,
-+ .component.invoke.args.qsig.AocInterim.type = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.currency = "Rupies",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 26,
-+ .component.invoke.args.qsig.AocInterim.type = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocInterim.specific.billing_id_present = 1,
-+ .component.invoke.args.qsig.AocInterim.specific.billing_id = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 27,
-+ .component.invoke.args.qsig.AocRate.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 28,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 0,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.special_charging_code = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 29,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.length = 8,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.scale = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 30,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.length = 8,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.scale = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity_present = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity.length = 20,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity.scale = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 31,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 2,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 32,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 3,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.currency = "Yen",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.amount.currency = 300,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.amount.multiplier = 5,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 33,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 2,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 2,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].currency_type = 3,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.currency = "Yen",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.amount.currency = 300,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.amount.multiplier = 5,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 34,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 35,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 5,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 36,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 6,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocComplete,
-+ .component.invoke.invoke_id = 37,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.length = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocComplete,
-+ .component.invoke.invoke_id = 38,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.length = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.str = "8340",
-+ .component.invoke.args.qsig.AocComplete.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocComplete.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocComplete.charging_association.id = 8298,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_AocComplete,
-+ .component.result.invoke_id = 39,
-+ .component.result.args.qsig.AocComplete.charging_option = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocDivChargeReq,
-+ .component.invoke.invoke_id = 40,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.length = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.str = "8340",
-+ .component.invoke.args.qsig.AocDivChargeReq.diversion_type = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocDivChargeReq,
-+ .component.invoke.invoke_id = 41,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.length = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.str = "8340",
-+ .component.invoke.args.qsig.AocDivChargeReq.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocDivChargeReq.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocDivChargeReq.charging_association.id = 8298,
-+ .component.invoke.args.qsig.AocDivChargeReq.diversion_type = 3,
-+ },
-+
-+ /* Q.SIG Call-Transfer-Operations (CT) */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferIdentify,
-+ .component.invoke.invoke_id = 42,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallTransferIdentify,
-+ .component.result.invoke_id = 43,
-+ .component.result.args.qsig.CallTransferIdentify.call_id = "2345",
-+ .component.result.args.qsig.CallTransferIdentify.rerouting_number.plan = 4,
-+ .component.result.args.qsig.CallTransferIdentify.rerouting_number.length = 4,
-+ .component.result.args.qsig.CallTransferIdentify.rerouting_number.str = "8340",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferAbandon,
-+ .component.invoke.invoke_id = 44,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferInitiate,
-+ .component.invoke.invoke_id = 45,
-+ .component.invoke.args.qsig.CallTransferInitiate.call_id = "2345",
-+ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.plan = 4,
-+ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.length = 4,
-+ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallTransferInitiate,
-+ .component.result.invoke_id = 46,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferSetup,
-+ .component.invoke.invoke_id = 47,
-+ .component.invoke.args.qsig.CallTransferSetup.call_id = "23",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallTransferSetup,
-+ .component.result.invoke_id = 48,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 49,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 50,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie_contents = "RT",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 51,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 52,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallTransferActive.connected_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.data = "Alphred",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 53,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 0,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.screening_indicator = 3,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.plan = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.length = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 54,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 55,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 56,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 3,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.screening_indicator = 3,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.plan = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.length = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 57,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie_contents = "RT",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 58,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 59,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.call_status = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 60,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallTransferComplete.call_status = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 61,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 62,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 63,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie_contents = "RT",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 64,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.data = "Alphred",
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie_contents = "RT",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_SubaddressTransfer,
-+ .component.invoke.invoke_id = 65,
-+ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.type = 1,
-+ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.length = 4,
-+ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.u.nsap = "4356",
-+ },
-+
-+ /* Q.SIG Call-Diversion-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ActivateDiversionQ,
-+ .component.invoke.invoke_id = 66,
-+ .component.invoke.args.qsig.ActivateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.ActivateDiversionQ.basic_service = 3,
-+ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.plan = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.length = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.str = "8340",
-+ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.plan = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.length = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_ActivateDiversionQ,
-+ .component.result.invoke_id = 67,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DeactivateDiversionQ,
-+ .component.invoke.invoke_id = 68,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.basic_service = 3,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.plan = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.length = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_DeactivateDiversionQ,
-+ .component.result.invoke_id = 69,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.invoke.invoke_id = 70,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.basic_service = 3,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.invoke.invoke_id = 71,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.basic_service = 0,/* default */
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 72,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 73,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 1,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].remote_enabled = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 74,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 1,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].remote_enabled = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 75,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].remote_enabled = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CheckRestriction,
-+ .component.invoke.invoke_id = 76,
-+ .component.invoke.args.qsig.CheckRestriction.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.CheckRestriction.served_user_number.length = 4,
-+ .component.invoke.args.qsig.CheckRestriction.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.CheckRestriction.basic_service = 3,
-+ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.plan = 4,
-+ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.length = 4,
-+ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CheckRestriction,
-+ .component.result.invoke_id = 77,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallRerouting,
-+ .component.invoke.invoke_id = 78,
-+ .component.invoke.args.qsig.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.qsig.CallRerouting.called.number.plan = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.length = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.str = "8340",
-+ .component.invoke.args.qsig.CallRerouting.diversion_counter = 5,
-+ .component.invoke.args.qsig.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.qsig.CallRerouting.subscription_option = 2,
-+ .component.invoke.args.qsig.CallRerouting.calling.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallRerouting,
-+ .component.invoke.invoke_id = 79,
-+ .component.invoke.args.qsig.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.qsig.CallRerouting.original_rerouting_reason_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_rerouting_reason = 2,
-+ .component.invoke.args.qsig.CallRerouting.called.number.plan = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.length = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.str = "8340",
-+ .component.invoke.args.qsig.CallRerouting.diversion_counter = 5,
-+ .component.invoke.args.qsig.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.qsig.CallRerouting.subscription_option = 2,
-+ .component.invoke.args.qsig.CallRerouting.calling_subaddress.type = 1,
-+ .component.invoke.args.qsig.CallRerouting.calling_subaddress.length = 4,
-+ .component.invoke.args.qsig.CallRerouting.calling_subaddress.u.nsap = "3253",
-+ .component.invoke.args.qsig.CallRerouting.calling.presentation = 1,
-+ .component.invoke.args.qsig.CallRerouting.calling_name_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.calling_name.presentation = 4,
-+ .component.invoke.args.qsig.CallRerouting.calling_name.char_set = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called.presentation = 2,
-+ .component.invoke.args.qsig.CallRerouting.redirecting_name_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.redirecting_name.presentation = 4,
-+ .component.invoke.args.qsig.CallRerouting.redirecting_name.char_set = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called_name_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called_name.presentation = 4,
-+ .component.invoke.args.qsig.CallRerouting.original_called_name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallRerouting,
-+ .component.result.invoke_id = 80,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation1,
-+ .component.invoke.invoke_id = 81,
-+ .component.invoke.args.qsig.DivertingLegInformation1.diversion_reason = 3,
-+ .component.invoke.args.qsig.DivertingLegInformation1.subscription_option = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.plan = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.length = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.str = "8340",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 82,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_counter = 6,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_reason = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 83,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_counter = 6,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_reason = 3,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_diversion_reason = 2,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diverting_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diverting.presentation = 2,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called.presentation = 2,
-+ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name.presentation = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name.char_set = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name.presentation = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name.char_set = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation3,
-+ .component.invoke.invoke_id = 84,
-+ .component.invoke.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation3,
-+ .component.invoke.invoke_id = 85,
-+ .component.invoke.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name.presentation = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name.char_set = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CfnrDivertedLegFailed,
-+ .component.invoke.invoke_id = 86,
-+ },
-+
-+ /* Q.SIG SS-MWI-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 102,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 103,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 0,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.integer = 532,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 104,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.str = "9838",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 105,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 2,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.str = "123456",
-+ .component.invoke.args.qsig.MWIActivate.number_of_messages_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.number_of_messages = 6548,
-+ .component.invoke.args.qsig.MWIActivate.originating_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.originating_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.originating_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.timestamp_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.timestamp = "19970621194530",
-+ .component.invoke.args.qsig.MWIActivate.priority_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.priority = 7,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIActivate,
-+ .component.result.invoke_id = 106,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIDeactivate,
-+ .component.invoke.invoke_id = 107,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIDeactivate.basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIDeactivate,
-+ .component.invoke.invoke_id = 108,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIDeactivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id.type = 0,
-+ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id.u.integer = 532,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIDeactivate,
-+ .component.result.invoke_id = 109,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.invoke.invoke_id = 110,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIInterrogate.basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.invoke.invoke_id = 111,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIInterrogate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id.type = 0,
-+ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id.u.integer = 532,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.result.invoke_id = 112,
-+ .component.result.args.qsig.MWIInterrogate.num_records = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.result.invoke_id = 113,
-+ .component.result.args.qsig.MWIInterrogate.num_records = 2,
-+ .component.result.args.qsig.MWIInterrogate.list[0].basic_service = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id.type = 0,
-+ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id.u.integer = 987,
-+ .component.result.args.qsig.MWIInterrogate.list[0].number_of_messages_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].number_of_messages = 6548,
-+ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.plan = 4,
-+ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.length = 4,
-+ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.str = "9838",
-+ .component.result.args.qsig.MWIInterrogate.list[0].timestamp_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].timestamp = "19970621194530",
-+ .component.result.args.qsig.MWIInterrogate.list[0].priority_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].priority = 7,
-+ .component.result.args.qsig.MWIInterrogate.list[1].basic_service = 1,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_dms100_msgs[] = {
-+/* *INDENT-OFF* */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_DMS100_RLT_OperationInd,
-+ .component.invoke.invoke_id = ROSE_DMS100_RLT_OPERATION_IND,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_DMS100_RLT_OperationInd,
-+ .component.result.invoke_id = ROSE_DMS100_RLT_OPERATION_IND,
-+ .component.result.args.dms100.RLT_OperationInd.call_id = 130363,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_DMS100_RLT_ThirdParty,
-+ .component.invoke.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY,
-+ .component.invoke.args.dms100.RLT_ThirdParty.call_id = 120047,
-+ .component.invoke.args.dms100.RLT_ThirdParty.reason = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_DMS100_RLT_ThirdParty,
-+ .component.result.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_ni2_msgs[] = {
-+/* *INDENT-OFF* */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_NI2_InformationFollowing,
-+ .component.invoke.invoke_id = 1,
-+ .component.invoke.args.ni2.InformationFollowing.value = 7,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_NI2_InitiateTransfer,
-+ .component.invoke.invoke_id = 2,
-+ .component.invoke.args.ni2.InitiateTransfer.call_reference = 5,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+/* ------------------------------------------------------------------- */
-+
-+static void rose_pri_message(struct pri *ctrl, char *stuff)
-+{
-+ fprintf(stdout, "%s", stuff);
-+}
-+
-+static void rose_pri_error(struct pri *ctrl, char *stuff)
-+{
-+ fprintf(stdout, "%s", stuff);
-+ fprintf(stderr, "%s", stuff);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Test ROSE encoding and decoding the given message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param index Message number to report.
-+ * \param header Facility message header data to encode.
-+ * \param encode_msg Message data to encode.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_test_msg(struct pri *ctrl, unsigned index,
-+ const struct fac_extension_header *header, const struct rose_message *encode_msg)
-+{
-+ struct fac_extension_header decoded_header;
-+ struct rose_message decoded_msg;
-+ unsigned char *enc_pos;
-+ unsigned char *enc_end;
-+ const unsigned char *dec_pos;
-+ const unsigned char *dec_end;
-+
-+ static unsigned char buf[1024];
-+
-+ pri_message(ctrl, "\n\n");
-+ enc_end = buf + sizeof(buf);
-+ enc_pos = facility_encode_header(ctrl, buf, enc_end, header);
-+ if (!enc_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to encode header\n", index);
-+ } else {
-+ enc_pos = rose_encode(ctrl, enc_pos, enc_end, encode_msg);
-+ if (!enc_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to encode ROSE\n", index);
-+ } else {
-+ pri_message(ctrl, "Message %u encoded length is %u\n", index,
-+ (unsigned) (enc_pos - buf));
-+
-+ /* Clear the decoded message contents for comparison. */
-+ memset(&decoded_header, 0, sizeof(decoded_header));
-+ memset(&decoded_msg, 0, sizeof(decoded_msg));
-+
-+ dec_end = enc_pos;
-+ dec_pos = facility_decode_header(ctrl, buf, dec_end, &decoded_header);
-+ if (!dec_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to decode header\n", index);
-+ } else {
-+ dec_pos = rose_decode(ctrl, dec_pos, dec_end, &decoded_msg);
-+ if (!dec_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to decode ROSE\n", index);
-+ } else {
-+ if (header
-+ && memcmp(header, &decoded_header, sizeof(decoded_header))) {
-+ pri_error(ctrl, "Error: Message:%u Header did not match\n",
-+ index);
-+ }
-+ if (memcmp(encode_msg, &decoded_msg, sizeof(decoded_msg))) {
-+ pri_error(ctrl, "Error: Message:%u ROSE did not match\n", index);
-+ }
-+ }
-+ }
-+ }
-+ }
-+ pri_message(ctrl, "\n\n"
-+ "************************************************************\n");
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Test ROSE decoding messages of unusual encodings.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Test name for the encoded message.
-+ * \param msg_buf Encoded message to decode.
-+ * \param msg_len Length of encoded message buffer.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_test_exception(struct pri *ctrl, const char *name,
-+ const unsigned char *msg, size_t msg_len)
-+{
-+ const unsigned char *pos;
-+ const unsigned char *end;
-+ struct fac_extension_header header;
-+ struct rose_message decoded_msg;
-+
-+ pri_message(ctrl, "\n\n"
-+ "%s test: Message encoded length is %u\n", name, (unsigned) msg_len);
-+
-+ pos = msg;
-+ end = msg + msg_len;
-+ pos = facility_decode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ pri_error(ctrl, "Error: %s test: Message failed to decode header\n", name);
-+ } else {
-+ pos = rose_decode(ctrl, pos, end, &decoded_msg);
-+ if (!pos) {
-+ pri_error(ctrl, "Error: %s test: Message failed to decode ROSE\n", name);
-+ }
-+ }
-+
-+ pri_message(ctrl, "\n\n"
-+ "************************************************************\n");
-+}
-+
-+/*!
-+ * \brief ROSE encode/decode test program.
-+ *
-+ * \param argc Program argument count.
-+ * \param argv Program argument string array.
-+ *
-+ * \retval 0 on success.
-+ * \retval Nonzero on error.
-+ */
-+int main(int argc, char *argv[])
-+{
-+ unsigned index;
-+ unsigned offset;
-+ static struct pri dummy_ctrl;
-+
-+ pri_set_message(rose_pri_message);
-+ pri_set_error(rose_pri_error);
-+
-+ memset(&dummy_ctrl, 0, sizeof(dummy_ctrl));
-+ dummy_ctrl.debug = PRI_DEBUG_APDU;
-+
-+ offset = 0;
-+ pri_message(&dummy_ctrl, "Encode/decode message(s)\n");
-+ if (argc <= 1) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
-+ for (index = 0; index < ARRAY_LEN(rose_etsi_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_etsi_msgs[index]);
-+ }
-+ offset += ARRAY_LEN(rose_etsi_msgs);
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
-+ for (index = 0; index < ARRAY_LEN(rose_qsig_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset,
-+ &fac_headers[index % ARRAY_LEN(fac_headers)], &rose_qsig_msgs[index]);
-+ }
-+ offset += ARRAY_LEN(rose_qsig_msgs);
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_DMS100;
-+ for (index = 0; index < ARRAY_LEN(rose_dms100_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_dms100_msgs[index]);
-+ }
-+ offset += ARRAY_LEN(rose_dms100_msgs);
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_NI2;
-+ for (index = 0; index < ARRAY_LEN(rose_ni2_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_ni2_msgs[index]);
-+ }
-+ //offset += ARRAY_LEN(rose_ni2_msgs);
-+ } else {
-+ index = atoi(argv[1]);
-+
-+ if (index < ARRAY_LEN(rose_etsi_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_etsi_msgs[index]);
-+ return 0;
-+ }
-+ offset += ARRAY_LEN(rose_etsi_msgs);
-+ index -= ARRAY_LEN(rose_etsi_msgs);
-+
-+ if (index < ARRAY_LEN(rose_qsig_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
-+ rose_test_msg(&dummy_ctrl, index + offset,
-+ &fac_headers[index % ARRAY_LEN(fac_headers)], &rose_qsig_msgs[index]);
-+ return 0;
-+ }
-+ offset += ARRAY_LEN(rose_qsig_msgs);
-+ index -= ARRAY_LEN(rose_qsig_msgs);
-+
-+ if (index < ARRAY_LEN(rose_dms100_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_DMS100;
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_dms100_msgs[index]);
-+ return 0;
-+ }
-+ offset += ARRAY_LEN(rose_dms100_msgs);
-+ index -= ARRAY_LEN(rose_dms100_msgs);
-+
-+ if (index < ARRAY_LEN(rose_ni2_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_NI2;
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_ni2_msgs[index]);
-+ return 0;
-+ }
-+ //offset += ARRAY_LEN(rose_ni2_msgs);
-+ //index -= ARRAY_LEN(rose_ni2_msgs);
-+
-+ fprintf(stderr, "Invalid option\n");
-+ return 0;
-+ }
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "Decode unusually encoded messages\n");
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
-+
-+ rose_test_exception(&dummy_ctrl, "Extra bytes on end", rose_etsi_extra,
-+ sizeof(rose_etsi_extra));
-+
-+ rose_test_exception(&dummy_ctrl, "Indefinite length", rose_etsi_indefinite_len,
-+ sizeof(rose_etsi_indefinite_len) - 2);
-+ rose_test_exception(&dummy_ctrl, "Indefinite length (extra)",
-+ rose_etsi_indefinite_len, sizeof(rose_etsi_indefinite_len));
-+
-+ rose_test_exception(&dummy_ctrl, "Unused components (indefinite length)",
-+ rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len) - 2);
-+ rose_test_exception(&dummy_ctrl, "Unused components (indefinite length, extra)",
-+ rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len));
-+
-+ rose_test_exception(&dummy_ctrl, "Unused components", rose_etsi_unused,
-+ sizeof(rose_etsi_unused) - 2);
-+ rose_test_exception(&dummy_ctrl, "Unused components (extra)", rose_etsi_unused,
-+ sizeof(rose_etsi_unused));
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "List of operation codes:\n");
-+ for (index = 0; index < ROSE_Num_Operation_Codes; ++index) {
-+ pri_message(&dummy_ctrl, "%d: %s\n", index, rose_operation2str(index));
-+ }
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "************************************************************\n");
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "List of error codes:\n");
-+ for (index = 0; index < ROSE_ERROR_Num_Codes; ++index) {
-+ pri_message(&dummy_ctrl, "%d: %s\n", index, rose_error2str(index));
-+ }
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "************************************************************\n");
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_message) = %u\n",
-+ (unsigned) sizeof(struct rose_message));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_invoke) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_invoke));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_result) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_result));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_error) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_error));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_reject) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_reject));
-+ pri_message(&dummy_ctrl, "sizeof(union rose_msg_invoke_args) = %u\n",
-+ (unsigned) sizeof(union rose_msg_invoke_args));
-+ pri_message(&dummy_ctrl, "sizeof(union rose_msg_result_args) = %u\n",
-+ (unsigned) sizeof(union rose_msg_result_args));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigForwardingList) = %u\n",
-+ (unsigned) sizeof(struct roseQsigForwardingList));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigCallRerouting_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseQsigCallRerouting_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigAocRateArg_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseQsigAocRateArg_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigMWIInterrogateRes) = %u\n",
-+ (unsigned) sizeof(struct roseQsigMWIInterrogateRes));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiForwardingList) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiForwardingList));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiServedUserNumberList) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiServedUserNumberList));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiCallRerouting_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiCallRerouting_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiDiversionInformation_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiDiversionInformation_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiAOCSCurrencyInfoList) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiAOCSCurrencyInfoList));
-+
-+/* ------------------------------------------------------------------- */
-+
-+ return 0;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rosetest.c */
-
-Property changes on: rosetest.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_internal.h
-===================================================================
---- a/rose_internal.h (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_internal.h (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,477 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Internal definitions and prototypes for ROSE.
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+#ifndef _LIBPRI_ROSE_INTERNAL_H
-+#define _LIBPRI_ROSE_INTERNAL_H
-+
-+#include "rose.h"
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/* Embedded-Q931-Types */
-+unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ unsigned tag, const struct roseQ931ie *q931ie);
-+
-+const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
-+ size_t contents_size);
-+
-+/* Addressing-Data-Elements */
-+unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePartyNumber *party_number);
-+unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePartySubaddress *party_subaddress);
-+unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ unsigned tag, const struct roseAddress *address);
-+unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedNumberUnscreened *party);
-+unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseNumberScreened *screened);
-+unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedNumberScreened *party);
-+unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseAddressScreened *screened);
-+unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedAddressScreened *party);
-+
-+const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *party_number);
-+const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartySubaddress *party_subaddress);
-+const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct roseAddress *address);
-+const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedNumberUnscreened *party);
-+const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseNumberScreened *screened);
-+const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedNumberScreened *party);
-+const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseAddressScreened *screened);
-+const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedAddressScreened *party);
-+
-+/* ETSI Advice-of-Charge (AOC) */
-+unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* ETSI Call Diversion */
-+unsigned char *rose_enc_etsi_ActivationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DeactivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_InterrogationDiversion_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_DiversionInformation_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_etsi_ActivationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DeactivationStatusNotificationDiv_ARG(struct pri
-+ *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_InterrogationDiversion_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_DiversionInformation_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* ETSI Explicit Call Transfer (ECT) */
-+unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+
-+/* Q.SIG Name-Operations */
-+unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct roseQsigName *name);
-+
-+const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigName *name);
-+
-+unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/*
-+ * Q.SIG Dummy invoke/result argument used by:
-+ * SS-AOC-Operations,
-+ * Call-Transfer-Operations,
-+ * Call-Diversion-Operations,
-+ * and SS-MWI-Operations.
-+ */
-+unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+
-+/* Q.SIG SS-AOC-Operations */
-+unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* Q.SIG Call-Diversion-Operations */
-+unsigned char *rose_enc_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* Q.SIG Call-Transfer-Operations (CT) */
-+unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* Q.SIG SS-MWI-Operations */
-+unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+
-+/* Northern Telecom DMS-100 operations */
-+unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* National ISDN 2 (NI2) operations */
-+unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* _LIBPRI_ROSE_INTERNAL_H */
-+/* ------------------------------------------------------------------- */
-+/* end rose_internal.h */
-
-Property changes on: rose_internal.h
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: pri_q921.h
-===================================================================
---- a/pri_q921.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_q921.h (.../branches/1.4) (revision 1357)
-@@ -192,4 +192,10 @@
-
- extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
-
-+extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
-+
-+extern pri_event *q921_dchannel_up(struct pri *pri);
-+
-+extern pri_event *q921_dchannel_down(struct pri *pri);
-+
- #endif
-Index: pri_facility.c
-===================================================================
---- a/pri_facility.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_facility.c (.../branches/1.4) (revision 1357)
-@@ -33,872 +33,1340 @@
- #include "pri_q921.h"
- #include "pri_q931.h"
- #include "pri_facility.h"
-+#include "rose.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
-
--static char *asn1id2text(int id)
-+static short get_invokeid(struct pri *ctrl)
- {
-- static char data[32];
-- static char *strings[] = {
-- "none",
-- "Boolean",
-- "Integer",
-- "Bit String",
-- "Octet String",
-- "NULL",
-- "Object Identifier",
-- "Object Descriptor",
-- "External Reference",
-- "Real Number",
-- "Enumerated",
-- "Embedded PDV",
-- "UTF-8 String",
-- "Relative Object ID",
-- "Reserved (0e)",
-- "Reserved (0f)",
-- "Sequence",
-- "Set",
-- "Numeric String",
-- "Printable String",
-- "Tele-Text String",
-- "IA-5 String",
-- "UTC Time",
-- "Generalized Time",
-- };
-- if (id > 0 && id <= 0x18) {
-- return strings[id];
-- } else {
-- sprintf(data, "Unknown (%02x)", id);
-- return data;
-- }
-+ ctrl = PRI_MASTER(ctrl);
-+ return ++ctrl->last_invoke;
- }
-
--static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
-+static int redirectingreason_from_q931(struct pri *ctrl, int redirectingreason)
- {
-- unsigned char *vdata = (unsigned char *)comp_ptr;
-- struct rose_component *comp;
-- int i = 0;
-- int j, k, l;
-- int clen = 0;
-+ int value;
-
-- while (len > 0) {
-- GET_COMPONENT(comp, i, vdata, len);
-- pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
-- if ((comp->type == 0) && (comp->len == 0))
-- return clen + 2;
-- if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
-- for (j = 0; j < comp->len; ++j)
-- pri_message(pri, " %02X", comp->data[j]);
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ switch (redirectingreason) {
-+ case PRI_REDIR_UNKNOWN:
-+ value = QSIG_DIVERT_REASON_UNKNOWN;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_BUSY:
-+ value = QSIG_DIVERT_REASON_CFB;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_NO_REPLY:
-+ value = QSIG_DIVERT_REASON_CFNR;
-+ break;
-+ case PRI_REDIR_UNCONDITIONAL:
-+ value = QSIG_DIVERT_REASON_CFU;
-+ break;
-+ case PRI_REDIR_DEFLECTION:
-+ case PRI_REDIR_DTE_OUT_OF_ORDER:
-+ case PRI_REDIR_FORWARDED_BY_DTE:
-+ pri_message(ctrl,
-+ "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n",
-+ redirectingreason);
-+ /* Fall through */
-+ default:
-+ value = QSIG_DIVERT_REASON_UNKNOWN;
-+ break;
- }
-- if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
-- switch (comp->type & ASN1_TYPE_MASK) {
-- case 0:
-- pri_message(pri, " (none)");
-- break;
-- case ASN1_BOOLEAN:
-- pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
-- break;
-- case ASN1_INTEGER:
-- for (k = l = 0; k < comp->len; ++k)
-- l = (l << 8) | comp->data[k];
-- pri_message(pri, " (INTEGER: %d)", l);
-- break;
-- case ASN1_BITSTRING:
-- pri_message(pri, " (BITSTRING:");
-- for (k = 0; k < comp->len; ++k)
-- pri_message(pri, " %02x", comp->data[k]);
-- pri_message(pri, ")");
-- break;
-- case ASN1_OCTETSTRING:
-- pri_message(pri, " (OCTETSTRING:");
-- for (k = 0; k < comp->len; ++k)
-- pri_message(pri, " %02x", comp->data[k]);
-- pri_message(pri, ")");
-- break;
-- case ASN1_NULL:
-- pri_message(pri, " (NULL)");
-- break;
-- case ASN1_OBJECTIDENTIFIER:
-- pri_message(pri, " (OBJECTIDENTIFIER:");
-- for (k = 0; k < comp->len; ++k)
-- pri_message(pri, " %02x", comp->data[k]);
-- pri_message(pri, ")");
-- break;
-- case ASN1_ENUMERATED:
-- for (k = l = 0; k < comp->len; ++k)
-- l = (l << 8) | comp->data[k];
-- pri_message(pri, " (ENUMERATED: %d)", l);
-- break;
-- case ASN1_SEQUENCE:
-- pri_message(pri, " (SEQUENCE)");
-- break;
-- default:
-- pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
-- break;
-- }
-+ break;
-+ default:
-+ switch (redirectingreason) {
-+ case PRI_REDIR_UNKNOWN:
-+ value = Q952_DIVERT_REASON_UNKNOWN;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_BUSY:
-+ value = Q952_DIVERT_REASON_CFB;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_NO_REPLY:
-+ value = Q952_DIVERT_REASON_CFNR;
-+ break;
-+ case PRI_REDIR_DEFLECTION:
-+ value = Q952_DIVERT_REASON_CD;
-+ break;
-+ case PRI_REDIR_UNCONDITIONAL:
-+ value = Q952_DIVERT_REASON_CFU;
-+ break;
-+ case PRI_REDIR_DTE_OUT_OF_ORDER:
-+ case PRI_REDIR_FORWARDED_BY_DTE:
-+ pri_message(ctrl,
-+ "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n",
-+ redirectingreason);
-+ /* Fall through */
-+ default:
-+ value = Q952_DIVERT_REASON_UNKNOWN;
-+ break;
- }
-- else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
-- pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
-+ break;
-+ }
-+
-+ return value;
-+}
-+
-+static int redirectingreason_for_q931(struct pri *ctrl, int redirectingreason)
-+{
-+ int value;
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ switch (redirectingreason) {
-+ case QSIG_DIVERT_REASON_UNKNOWN:
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
-+ case QSIG_DIVERT_REASON_CFU:
-+ value = PRI_REDIR_UNCONDITIONAL;
-+ break;
-+ case QSIG_DIVERT_REASON_CFB:
-+ value = PRI_REDIR_FORWARD_ON_BUSY;
-+ break;
-+ case QSIG_DIVERT_REASON_CFNR:
-+ value = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unknown Q.SIG diversion reason %d\n",
-+ redirectingreason);
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
- }
-- else {
-- pri_message(pri, " (component %02x)", comp->type);
-+ break;
-+ default:
-+ switch (redirectingreason) {
-+ case Q952_DIVERT_REASON_UNKNOWN:
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
-+ case Q952_DIVERT_REASON_CFU:
-+ value = PRI_REDIR_UNCONDITIONAL;
-+ break;
-+ case Q952_DIVERT_REASON_CFB:
-+ value = PRI_REDIR_FORWARD_ON_BUSY;
-+ break;
-+ case Q952_DIVERT_REASON_CFNR:
-+ value = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ break;
-+ case Q952_DIVERT_REASON_CD:
-+ value = PRI_REDIR_DEFLECTION;
-+ break;
-+ case Q952_DIVERT_REASON_IMMEDIATE:
-+ pri_message(ctrl,
-+ "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
-+ value = PRI_REDIR_UNKNOWN; /* ??? */
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unknown Q.952 diversion reason %d\n",
-+ redirectingreason);
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
- }
-- pri_message(pri, "\n");
-- if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
-- j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
-- else
-- j = comp->len;
-- j += 2;
-- len -= j;
-- vdata += j;
-- clen += j;
-+ break;
- }
-- return clen;
-+
-+ return value;
- }
-
--int asn1_dump(struct pri *pri, void *comp, int len)
-+/*!
-+ * \brief Convert the Q.931 type-of-number field to facility.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param ton Q.931 ton/plan octet.
-+ *
-+ * \return PartyNumber enumeration value.
-+ */
-+static int typeofnumber_from_q931(struct pri *ctrl, int ton)
- {
-- return asn1_dumprecursive(pri, comp, len, 0);
-+ int value;
-+
-+ switch ((ton >> 4) & 0x03) {
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
-+ /* fall through */
-+ case PRI_TON_UNKNOWN:
-+ value = Q932_TON_UNKNOWN;
-+ break;
-+ case PRI_TON_INTERNATIONAL:
-+ value = Q932_TON_INTERNATIONAL;
-+ break;
-+ case PRI_TON_NATIONAL:
-+ value = Q932_TON_NATIONAL;
-+ break;
-+ case PRI_TON_NET_SPECIFIC:
-+ value = Q932_TON_NET_SPECIFIC;
-+ break;
-+ case PRI_TON_SUBSCRIBER:
-+ value = Q932_TON_SUBSCRIBER;
-+ break;
-+ case PRI_TON_ABBREVIATED:
-+ value = Q932_TON_ABBREVIATED;
-+ break;
-+ }
-+
-+ return value;
- }
-
--static unsigned char get_invokeid(struct pri *pri)
-+static int typeofnumber_for_q931(struct pri *ctrl, int ton)
- {
-- return ++pri->last_invoke;
-+ int value;
-+
-+ switch (ton) {
-+ default:
-+ pri_message(ctrl, "!! Invalid TypeOfNumber %d\n", ton);
-+ /* fall through */
-+ case Q932_TON_UNKNOWN:
-+ value = PRI_TON_UNKNOWN;
-+ break;
-+ case Q932_TON_INTERNATIONAL:
-+ value = PRI_TON_INTERNATIONAL;
-+ break;
-+ case Q932_TON_NATIONAL:
-+ value = PRI_TON_NATIONAL;
-+ break;
-+ case Q932_TON_NET_SPECIFIC:
-+ value = PRI_TON_NET_SPECIFIC;
-+ break;
-+ case Q932_TON_SUBSCRIBER:
-+ value = PRI_TON_SUBSCRIBER;
-+ break;
-+ case Q932_TON_ABBREVIATED:
-+ value = PRI_TON_ABBREVIATED;
-+ break;
-+ }
-+
-+ return value << 4;
- }
-
--struct addressingdataelements_presentednumberunscreened {
-- char partyaddress[21];
-- char partysubaddress[21];
-- int npi; /* Numbering Plan Indicator */
-- int ton; /* Type Of Number */
-- int pres; /* Presentation */
--};
-+/*!
-+ * \internal
-+ * \brief Convert the Q.931 numbering plan field to facility.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param plan Q.931 ton/plan octet.
-+ *
-+ * \return PartyNumber enumeration value.
-+ */
-+static int numbering_plan_from_q931(struct pri *ctrl, int plan)
-+{
-+ int value;
-
--struct addressingdataelements_presentednumberscreened {
-- char partyaddress[21];
-- char partysubaddress[21];
-- int npi; /* Numbering Plan Indicator */
-- int ton; /* Type Of Number */
-- int pres; /* Presentation */
-- int scrind; /* Screening Indicator */
--};
-+ switch (plan & 0x0F) {
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 numbering plan value (%d)\n", plan);
-+ /* fall through */
-+ case PRI_NPI_UNKNOWN:
-+ value = 0; /* unknown */
-+ break;
-+ case PRI_NPI_E163_E164:
-+ value = 1; /* public */
-+ break;
-+ case PRI_NPI_X121:
-+ value = 3; /* data */
-+ break;
-+ case PRI_NPI_F69:
-+ value = 4; /* telex */
-+ break;
-+ case PRI_NPI_NATIONAL:
-+ value = 8; /* nationalStandard */
-+ break;
-+ case PRI_NPI_PRIVATE:
-+ value = 5; /* private */
-+ break;
-+ }
-
--#define PRI_CHECKOVERFLOW(size) \
-- if (msgptr - message + (size) >= sizeof(message)) { \
-- *msgptr = '\0'; \
-- pri_message(pri, "%s", message); \
-- msgptr = message; \
-- }
-+ return value;
-+}
-
--static void dump_apdu(struct pri *pri, unsigned char *c, int len)
-+/*!
-+ * \internal
-+ * \brief Convert the PartyNumber numbering plan to Q.931 plan field value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param plan PartyNumber enumeration value.
-+ *
-+ * \return Q.931 plan field value.
-+ */
-+static int numbering_plan_for_q931(struct pri *ctrl, int plan)
- {
-- #define MAX_APDU_LENGTH 255
-- static char hexs[16] = "0123456789ABCDEF";
-- int i;
-- char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
-- char *msgptr;
--
-- msgptr = message;
-- *msgptr++ = ' ';
-- *msgptr++ = '[';
-- for (i=0; i<len; i++) {
-- PRI_CHECKOVERFLOW(3);
-- *msgptr++ = ' ';
-- *msgptr++ = hexs[(c[i] >> 4) & 0x0f];
-- *msgptr++ = hexs[(c[i]) & 0x0f];
-+ int value;
-+
-+ switch (plan) {
-+ default:
-+ pri_message(ctrl,
-+ "!! Unsupported PartyNumber to Q.931 numbering plan value (%d)\n", plan);
-+ /* fall through */
-+ case 0: /* unknown */
-+ value = PRI_NPI_UNKNOWN;
-+ break;
-+ case 1: /* public */
-+ value = PRI_NPI_E163_E164;
-+ break;
-+ case 3: /* data */
-+ value = PRI_NPI_X121;
-+ break;
-+ case 4: /* telex */
-+ value = PRI_NPI_F69;
-+ break;
-+ case 5: /* private */
-+ value = PRI_NPI_PRIVATE;
-+ break;
-+ case 8: /* nationalStandard */
-+ value = PRI_NPI_NATIONAL;
-+ break;
- }
-- PRI_CHECKOVERFLOW(6);
-- strcpy(msgptr, " ] - [");
-- msgptr += strlen(msgptr);
-- for (i=0; i<len; i++) {
-- PRI_CHECKOVERFLOW(1);
-- *msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
-+
-+ return value;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the Q.931 number presentation field to facility.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Q.931 presentation/screening octet.
-+ * \param number_present Non-zero if the number is available.
-+ *
-+ * \return Presented<Number/Address><Screened/Unscreened> enumeration value.
-+ */
-+static int presentation_from_q931(struct pri *ctrl, int presentation, int number_present)
-+{
-+ int value;
-+
-+ switch (presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ value = 0; /* presentationAllowed<Number/Address> */
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case PRI_PRES_RESTRICTED:
-+ if (number_present) {
-+ value = 3; /* presentationRestricted<Number/Address> */
-+ } else {
-+ value = 1; /* presentationRestricted */
-+ }
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ value = 2; /* numberNotAvailableDueToInterworking */
-+ break;
- }
-- PRI_CHECKOVERFLOW(2);
-- *msgptr++ = ']';
-- *msgptr++ = '\n';
-- *msgptr = '\0';
-- pri_message(pri, "%s", message);
-+
-+ return value;
- }
--#undef PRI_CHECKOVERFLOW
-
--int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
-+/*!
-+ * \internal
-+ * \brief Convert the Presented<Number/Address><Screened/Unscreened> presentation
-+ * to Q.931 presentation field value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Presented<Number/Address><Screened/Unscreened> value.
-+ *
-+ * \return Q.931 presentation field value.
-+ */
-+static int presentation_for_q931(struct pri *ctrl, int presentation)
- {
-- switch(pri->switchtype) {
-- case PRI_SWITCH_QSIG:
-- switch(redirectingreason) {
-- case PRI_REDIR_UNKNOWN:
-- return QSIG_DIVERT_REASON_UNKNOWN;
-- case PRI_REDIR_FORWARD_ON_BUSY:
-- return QSIG_DIVERT_REASON_CFB;
-- case PRI_REDIR_FORWARD_ON_NO_REPLY:
-- return QSIG_DIVERT_REASON_CFNR;
-- case PRI_REDIR_UNCONDITIONAL:
-- return QSIG_DIVERT_REASON_CFU;
-- case PRI_REDIR_DEFLECTION:
-- case PRI_REDIR_DTE_OUT_OF_ORDER:
-- case PRI_REDIR_FORWARDED_BY_DTE:
-- pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
-- /* Fall through */
-- default:
-- return QSIG_DIVERT_REASON_UNKNOWN;
-- }
-- default:
-- switch(redirectingreason) {
-- case PRI_REDIR_UNKNOWN:
-- return Q952_DIVERT_REASON_UNKNOWN;
-- case PRI_REDIR_FORWARD_ON_BUSY:
-- return Q952_DIVERT_REASON_CFB;
-- case PRI_REDIR_FORWARD_ON_NO_REPLY:
-- return Q952_DIVERT_REASON_CFNR;
-- case PRI_REDIR_DEFLECTION:
-- return Q952_DIVERT_REASON_CD;
-- case PRI_REDIR_UNCONDITIONAL:
-- return Q952_DIVERT_REASON_CFU;
-- case PRI_REDIR_DTE_OUT_OF_ORDER:
-- case PRI_REDIR_FORWARDED_BY_DTE:
-- pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason);
-- /* Fall through */
-- default:
-- return Q952_DIVERT_REASON_UNKNOWN;
-- }
-+ int value;
-+
-+ switch (presentation) {
-+ case 0: /* presentationAllowed<Number/Address> */
-+ value = PRI_PRES_ALLOWED;
-+ break;
-+ default:
-+ pri_message(ctrl,
-+ "!! Unsupported Presented<Number/Address><Screened/Unscreened> to Q.931 value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case 1: /* presentationRestricted */
-+ case 3: /* presentationRestricted<Number/Address> */
-+ value = PRI_PRES_RESTRICTED;
-+ break;
-+ case 2: /* numberNotAvailableDueToInterworking */
-+ value = PRI_PRES_UNAVAILABLE;
-+ break;
- }
-+
-+ return value;
- }
-
--static int redirectingreason_for_q931(struct pri *pri, int redirectingreason)
-+/*!
-+ * \internal
-+ * \brief Convert the Q.931 number presentation field to Q.SIG name presentation.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Q.931 presentation/screening octet.
-+ * \param name_present Non-zero if the name is available.
-+ *
-+ * \return Name presentation enumeration value.
-+ */
-+static int qsig_name_presentation_from_q931(struct pri *ctrl, int presentation, int name_present)
- {
-- switch(pri->switchtype) {
-- case PRI_SWITCH_QSIG:
-- switch(redirectingreason) {
-- case QSIG_DIVERT_REASON_UNKNOWN:
-- return PRI_REDIR_UNKNOWN;
-- case QSIG_DIVERT_REASON_CFU:
-- return PRI_REDIR_UNCONDITIONAL;
-- case QSIG_DIVERT_REASON_CFB:
-- return PRI_REDIR_FORWARD_ON_BUSY;
-- case QSIG_DIVERT_REASON_CFNR:
-- return PRI_REDIR_FORWARD_ON_NO_REPLY;
-- default:
-- pri_message(pri, "!! Unknown Q.SIG diversion reason %d\n", redirectingreason);
-- return PRI_REDIR_UNKNOWN;
-- }
-- default:
-- switch(redirectingreason) {
-- case Q952_DIVERT_REASON_UNKNOWN:
-- return PRI_REDIR_UNKNOWN;
-- case Q952_DIVERT_REASON_CFU:
-- return PRI_REDIR_UNCONDITIONAL;
-- case Q952_DIVERT_REASON_CFB:
-- return PRI_REDIR_FORWARD_ON_BUSY;
-- case Q952_DIVERT_REASON_CFNR:
-- return PRI_REDIR_FORWARD_ON_NO_REPLY;
-- case Q952_DIVERT_REASON_CD:
-- return PRI_REDIR_DEFLECTION;
-- case Q952_DIVERT_REASON_IMMEDIATE:
-- pri_message(pri, "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
-- return PRI_REDIR_UNKNOWN; /* ??? */
-- default:
-- pri_message(pri, "!! Unknown Q.952 diversion reason %d\n", redirectingreason);
-- return PRI_REDIR_UNKNOWN;
-- }
-+ int value;
-+
-+ switch (presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ if (name_present) {
-+ value = 1; /* presentation_allowed */
-+ } else {
-+ value = 4; /* name_not_available */
-+ }
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case PRI_PRES_RESTRICTED:
-+ if (name_present) {
-+ value = 2; /* presentation_restricted */
-+ } else {
-+ value = 3; /* presentation_restricted_null */
-+ }
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ value = 4; /* name_not_available */
-+ break;
- }
-+
-+ return value;
- }
-
--int typeofnumber_from_q931(struct pri *pri, int ton)
-+/*!
-+ * \internal
-+ * \brief Convert the Q.SIG name presentation to Q.931 presentation field value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Q.SIG name presentation value.
-+ *
-+ * \return Q.931 presentation field value.
-+ */
-+static int qsig_name_presentation_for_q931(struct pri *ctrl, int presentation)
- {
-- switch(ton) {
-- case PRI_TON_INTERNATIONAL:
-- return Q932_TON_INTERNATIONAL;
-- case PRI_TON_NATIONAL:
-- return Q932_TON_NATIONAL;
-- case PRI_TON_NET_SPECIFIC:
-- return Q932_TON_NET_SPECIFIC;
-- case PRI_TON_SUBSCRIBER:
-- return Q932_TON_SUBSCRIBER;
-- case PRI_TON_ABBREVIATED:
-- return Q932_TON_ABBREVIATED;
-- case PRI_TON_RESERVED:
-- default:
-- pri_message(pri, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
-- /* fall through */
-- case PRI_TON_UNKNOWN:
-- return Q932_TON_UNKNOWN;
-+ int value;
-+
-+ switch (presentation) {
-+ case 1: /* presentation_allowed */
-+ value = PRI_PRES_ALLOWED;
-+ break;
-+ default:
-+ pri_message(ctrl,
-+ "!! Unsupported Q.SIG name presentation to Q.931 value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case 2: /* presentation_restricted */
-+ case 3: /* presentation_restricted_null */
-+ value = PRI_PRES_RESTRICTED;
-+ break;
-+ case 0: /* optional_name_not_present */
-+ case 4: /* name_not_available */
-+ value = PRI_PRES_UNAVAILABLE;
-+ break;
- }
-+
-+ return value;
- }
-
--static int typeofnumber_for_q931(struct pri *pri, int ton)
-+/*!
-+ * \internal
-+ * \brief Convert number presentation to Q.SIG diversion subscription notification.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Number presentation value.
-+ *
-+ * \return Q.SIG diversion subscription notification value.
-+ */
-+static int presentation_to_subscription(struct pri *ctrl, int presentation)
- {
-- switch (ton) {
-- case Q932_TON_UNKNOWN:
-- return PRI_TON_UNKNOWN;
-- case Q932_TON_INTERNATIONAL:
-- return PRI_TON_INTERNATIONAL;
-- case Q932_TON_NATIONAL:
-- return PRI_TON_NATIONAL;
-- case Q932_TON_NET_SPECIFIC:
-- return PRI_TON_NET_SPECIFIC;
-- case Q932_TON_SUBSCRIBER:
-- return PRI_TON_SUBSCRIBER;
-- case Q932_TON_ABBREVIATED:
-- return PRI_TON_ABBREVIATED;
-- default:
-- pri_message(pri, "!! Invalid Q.932 TypeOfNumber %d\n", ton);
-- return PRI_TON_UNKNOWN;
-+ /* derive subscription value from presentation value */
-+
-+ switch (presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
-+ case PRI_PRES_RESTRICTED:
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
-+ case PRI_PRES_UNAVAILABLE: /* Number not available due to interworking */
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR; /* ?? QSIG_NO_NOTIFICATION */
-+ default:
-+ pri_message(ctrl, "!! Unknown Q.SIG presentationIndicator 0x%02x\n",
-+ presentation);
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
- }
- }
-
--int asn1_name_decode(void * data, int len, char *namebuf, int buflen)
-+/*!
-+ * \internal
-+ * \brief Copy the given rose party number to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_number Q.931 party number structure
-+ * \param rose_number ROSE party number structure
-+ *
-+ * \note It is assumed that the q931_number has been initialized before calling.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_number_to_q931(struct pri *ctrl,
-+ struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
- {
-- struct rose_component *comp = (struct rose_component*)data;
-- int datalen = 0, res = 0;
-+ //q931_party_number_init(q931_number);
-+ libpri_copy_string(q931_number->str, (char *) rose_number->str,
-+ sizeof(q931_number->str));
-+ q931_number->plan = numbering_plan_for_q931(ctrl, rose_number->plan)
-+ | typeofnumber_for_q931(ctrl, rose_number->ton);
-+ q931_number->valid = 1;
-+}
-
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char *)comp->data);
-- res = datalen + 2;
-- } else
-- datalen = res = comp->len;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose subaddress to the q931_party_subaddress.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ * \param rose_subaddress ROSE subaddress structure
-+ *
-+ * \note It is assumed that the q931_subaddress has been initialized before calling.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_subaddress_to_q931(struct pri *ctrl,
-+ struct q931_party_subaddress *q931_subaddress,
-+ const struct rosePartySubaddress *rose_subaddress)
-+{
-+ //q931_party_subaddress_init(q931_subaddress);
-+ if (!rose_subaddress->length) {
-+ /* Subaddress is not present. */
-+ return;
-+ }
-
-- if (datalen > buflen) {
-- /* Truncate */
-- datalen = buflen;
-+ switch (rose_subaddress->type) {
-+ case 0:/* UserSpecified */
-+ q931_subaddress->type = 2;/* user_specified */
-+ q931_subaddress->valid = 1;
-+ q931_subaddress->length = rose_subaddress->length;
-+ if (sizeof(q931_subaddress->data) <= q931_subaddress->length) {
-+ q931_subaddress->length = sizeof(q931_subaddress->data) - 1;
-+ }
-+ memcpy(q931_subaddress->data, rose_subaddress->u.user_specified.information,
-+ q931_subaddress->length);
-+ q931_subaddress->data[q931_subaddress->length] = '\0';
-+ if (rose_subaddress->u.user_specified.odd_count_present) {
-+ q931_subaddress->odd_even_indicator =
-+ rose_subaddress->u.user_specified.odd_count;
-+ }
-+ break;
-+ case 1:/* NSAP */
-+ q931_subaddress->type = 0;/* nsap */
-+ q931_subaddress->valid = 1;
-+ libpri_copy_string((char *) q931_subaddress->data,
-+ (char *) rose_subaddress->u.nsap, sizeof(q931_subaddress->data));
-+ q931_subaddress->length = strlen((char *) q931_subaddress->data);
-+ break;
-+ default:
-+ /* Don't know how to encode so assume it is not present. */
-+ break;
- }
-- memcpy(namebuf, comp->data, datalen);
-- return res + 2;
- }
-
--int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len)
-+/*!
-+ * \internal
-+ * \brief Copy the given rose address to the q931_party_id address.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_address Q.931 party id structure to fill address
-+ * \param rose_address ROSE address structure
-+ *
-+ * \note It is assumed that the q931_address has been initialized before calling.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_address_to_q931(struct pri *ctrl,
-+ struct q931_party_id *q931_address, const struct roseAddress *rose_address)
- {
-- struct rose_component *comp = NULL;
--
-- if (len < 2 + src_len)
-- return -1;
-+ rose_copy_number_to_q931(ctrl, &q931_address->number, &rose_address->number);
-+ rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
-+ &rose_address->subaddress);
-+}
-
-- if (max_len && (src_len > max_len))
-- src_len = max_len;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose presented screened party number to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_number Q.931 party number structure
-+ * \param rose_presented ROSE presented screened party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
-+ struct q931_party_number *q931_number,
-+ const struct rosePresentedNumberScreened *rose_presented)
-+{
-+ q931_party_number_init(q931_number);
-+ q931_number->valid = 1;
-+ q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
-+ switch (rose_presented->presentation) {
-+ case 0: /* presentationAllowedNumber */
-+ case 3: /* presentationRestrictedNumber */
-+ q931_number->presentation |=
-+ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
-+ rose_copy_number_to_q931(ctrl, q931_number,
-+ &rose_presented->screened.number);
-+ break;
-+ default:
-+ q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-+}
-
-- comp = (struct rose_component *)data;
-- comp->type = asn1_type;
-- comp->len = src_len;
-- memcpy(comp->data, src, src_len);
--
-- return 2 + src_len;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose presented unscreened party number to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_number Q.931 party number structure
-+ * \param rose_presented ROSE presented unscreened party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
-+ struct q931_party_number *q931_number,
-+ const struct rosePresentedNumberUnscreened *rose_presented)
-+{
-+ q931_party_number_init(q931_number);
-+ q931_number->valid = 1;
-+ q931_number->presentation = presentation_for_q931(ctrl,
-+ rose_presented->presentation) | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ switch (rose_presented->presentation) {
-+ case 0: /* presentationAllowedNumber */
-+ case 3: /* presentationRestrictedNumber */
-+ rose_copy_number_to_q931(ctrl, q931_number, &rose_presented->number);
-+ break;
-+ default:
-+ break;
-+ }
- }
-
--int asn1_copy_string(char * buf, int buflen, struct rose_component *comp)
-+/*!
-+ * \internal
-+ * \brief Copy the given rose presented screened party address to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_address Q.931 party id structure to fill the address
-+ * \param rose_presented ROSE presented screened party address structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
-+ struct q931_party_id *q931_address,
-+ const struct rosePresentedAddressScreened *rose_presented)
- {
-- int res;
-- int datalen;
-+ q931_party_number_init(&q931_address->number);
-+ q931_party_subaddress_init(&q931_address->subaddress);
-+ q931_address->number.valid = 1;
-+ q931_address->number.presentation = presentation_for_q931(ctrl,
-+ rose_presented->presentation);
-+ switch (rose_presented->presentation) {
-+ case 0: /* presentationAllowedAddress */
-+ case 3: /* presentationRestrictedAddress */
-+ q931_address->number.presentation |=
-+ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
-+ rose_copy_number_to_q931(ctrl, &q931_address->number,
-+ &rose_presented->screened.number);
-+ rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
-+ &rose_presented->screened.subaddress);
-+ break;
-+ default:
-+ q931_address->number.presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-+}
-
-- if ((comp->len > buflen) && (comp->len != ASN1_LEN_INDEF))
-- return -1;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose party name to the q931_party_name
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param qsig_name Q.SIG party name structure
-+ * \param rose_name Q.SIG ROSE party name structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_name_to_q931(struct pri *ctrl,
-+ struct q931_party_name *qsig_name, const struct roseQsigName *rose_name)
-+{
-+ //q931_party_name_init(qsig_name);
-+ qsig_name->valid = 1;
-+ qsig_name->presentation = qsig_name_presentation_for_q931(ctrl,
-+ rose_name->presentation);
-+ qsig_name->char_set = rose_name->char_set;
-+ libpri_copy_string(qsig_name->str, (char *) rose_name->data, sizeof(qsig_name->str));
-+}
-
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char*)comp->data);
-- res = datalen + 2;
-- } else
-- res = datalen = comp->len;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose party number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_number ROSE party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_number_to_rose(struct pri *ctrl,
-+ struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number)
-+{
-+ rose_number->plan = numbering_plan_from_q931(ctrl, q931_number->plan);
-+ rose_number->ton = typeofnumber_from_q931(ctrl, q931_number->plan);
-+ /* Truncate the q931_number->str if necessary. */
-+ libpri_copy_string((char *) rose_number->str, q931_number->str,
-+ sizeof(rose_number->str));
-+ rose_number->length = strlen((char *) rose_number->str);
-+}
-
-- memcpy(buf, comp->data, datalen);
-- buf[datalen] = 0;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_subaddress to the rose subaddress.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_subaddress ROSE subaddress structure
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_subaddress_to_rose(struct pri *ctrl,
-+ struct rosePartySubaddress *rose_subaddress,
-+ const struct q931_party_subaddress *q931_subaddress)
-+{
-+ if (!q931_subaddress->valid) {
-+ /* Subaddress is not present. */
-+ rose_subaddress->length = 0;
-+ return;
-+ }
-
-- return res;
-+ switch (q931_subaddress->type) {
-+ case 0: /* NSAP */
-+ rose_subaddress->type = 1;/* NSAP */
-+ libpri_copy_string((char *) rose_subaddress->u.nsap,
-+ (char *) q931_subaddress->data, sizeof(rose_subaddress->u.nsap));
-+ rose_subaddress->length = strlen((char *) rose_subaddress->u.nsap);
-+ break;
-+ case 2: /* user_specified */
-+ rose_subaddress->type = 0;/* UserSpecified */
-+ rose_subaddress->length = q931_subaddress->length;
-+ if (sizeof(rose_subaddress->u.user_specified.information)
-+ <= rose_subaddress->length) {
-+ rose_subaddress->length =
-+ sizeof(rose_subaddress->u.user_specified.information) - 1;
-+ } else {
-+ if (q931_subaddress->odd_even_indicator) {
-+ rose_subaddress->u.user_specified.odd_count_present = 1;
-+ rose_subaddress->u.user_specified.odd_count = 1;
-+ }
-+ }
-+ memcpy(rose_subaddress->u.user_specified.information, q931_subaddress->data,
-+ rose_subaddress->length);
-+ rose_subaddress->u.user_specified.information[rose_subaddress->length] = '\0';
-+ break;
-+ default:
-+ /* Don't know how to encode so assume it is not present. */
-+ rose_subaddress->length = 0;
-+ break;
-+ }
- }
-
--static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_id address to the rose address.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_address ROSE address structure
-+ * \param q931_address Q.931 party id structure to give address
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address,
-+ const struct q931_party_id *q931_address)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int datalen = 0;
-- int res = 0;
-+ q931_copy_number_to_rose(ctrl, &rose_address->number, &q931_address->number);
-+ q931_copy_subaddress_to_rose(ctrl, &rose_address->subaddress,
-+ &q931_address->subaddress);
-+}
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
-- if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) {
-- pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len);
-- return -1;
-- }
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char *)comp->data);
-- res = datalen + 2;
-- } else
-- res = datalen = comp->len;
--
-- memcpy(value->partyaddress, comp->data, datalen);
-- value->partyaddress[datalen] = '\0';
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose presented screened party number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_presented ROSE presented screened party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
-+ struct rosePresentedNumberScreened *rose_presented,
-+ const struct q931_party_number *q931_number)
-+{
-+ if (q931_number->valid) {
-+ rose_presented->presentation =
-+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
-+ rose_presented->screened.screening_indicator =
-+ q931_number->presentation & PRI_PRES_NUMBER_TYPE;
-+ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
-+ } else {
-+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
-+ }
-+}
-
-- return res + 2;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose presented unscreened party number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_presented ROSE presented unscreened party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
-+ struct rosePresentedNumberUnscreened *rose_presented,
-+ const struct q931_party_number *q931_number)
-+{
-+ if (q931_number->valid) {
-+ rose_presented->presentation =
-+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
-+ q931_copy_number_to_rose(ctrl, &rose_presented->number, q931_number);
-+ } else {
-+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
- }
-- while(0);
--
-- return -1;
- }
-
--static int rose_public_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+#if 0 /* In case it is needed in the future */
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose presented screened party address
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_presented ROSE presented screened party address structure
-+ * \param q931_address Q.931 party id structure to get the address
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
-+ struct rosePresentedAddressScreened *rose_presented,
-+ const struct q931_party_id *q931_address)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int ton;
-- int res = 0;
-+ if (q931_address->number.valid) {
-+ rose_presented->presentation =
-+ presentation_from_q931(ctrl, q931_address->number.presentation,
-+ q931_address->number.str[0]);
-+ rose_presented->screened.screening_indicator =
-+ q931_address->number.presentation & PRI_PRES_NUMBER_TYPE;
-+ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number,
-+ &q931_address->number);
-+ q931_copy_subaddress_to_rose(ctrl, &rose_presented->screened.subaddress,
-+ &q931_address->subaddress);
-+ } else {
-+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
-+ }
-+}
-+#endif /* In case it is needed in the future */
-
-- if (len < 2)
-- return -1;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_name to the rose party name
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_name Q.SIG ROSE party name structure
-+ * \param qsig_name Q.SIG party name structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_name_to_rose(struct pri *ctrl,
-+ struct roseQsigName *rose_name, const struct q931_party_name *qsig_name)
-+{
-+ if (qsig_name->valid) {
-+ rose_name->presentation = qsig_name_presentation_from_q931(ctrl,
-+ qsig_name->presentation, qsig_name->str[0]);
-+ rose_name->char_set = qsig_name->char_set;
-+ /* Truncate the qsig_name->str if necessary. */
-+ libpri_copy_string((char *) rose_name->data, qsig_name->str, sizeof(rose_name->data));
-+ rose_name->length = strlen((char *) rose_name->data);
-+ } else {
-+ rose_name->presentation = 4;/* name_not_available */
-+ }
-+}
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, ton);
-- NEXT_COMPONENT(comp, i);
-- ton = typeofnumber_for_q931(pri, ton);
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG DivertingLegInformation1 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 1.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_diverting_leg_information1(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
-- if (res < 0)
-- return -1;
-- value->ton = ton;
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- return res + 3;
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_DivertingLegInformation1;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.DivertingLegInformation1.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-
-- } while(0);
-- return -1;
-+ /* subscriptionOption is the redirecting.to.number.presentation */
-+ msg.args.qsig.DivertingLegInformation1.subscription_option =
-+ presentation_to_subscription(ctrl, call->redirecting.to.number.presentation);
-+
-+ /* nominatedNr is the redirecting.to.number */
-+ q931_copy_number_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation1.nominated_number,
-+ &call->redirecting.to.number);
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI DivertingLegInformation1 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 1.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_diverting_leg_information1(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int ton;
-- int res = 0;
-+ struct rose_msg_invoke msg;
-
-- if (len < 2)
-- return -1;
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PrivatePartyNumber ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, ton);
-- NEXT_COMPONENT(comp, i);
-- ton = typeofnumber_for_q931(pri, ton);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_DivertingLegInformation1;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.etsi.DivertingLegInformation1.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-
-- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
-- if (res < 0)
-- return -1;
-- value->ton = ton;
-+ if (call->redirecting.to.number.valid) {
-+ msg.args.etsi.DivertingLegInformation1.subscription_option = 2;
-
-- return res + 3;
-+ /* divertedToNumber is the redirecting.to.number */
-+ msg.args.etsi.DivertingLegInformation1.diverted_to_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.DivertingLegInformation1.diverted_to,
-+ &call->redirecting.to.number);
-+ } else {
-+ msg.args.etsi.DivertingLegInformation1.subscription_option = 1;
-+ }
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- } while(0);
-- return -1;
-+ return pos;
- }
-
--static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \brief Encode and queue the DivertingLegInformation1 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode diversion leg 1.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_diverting_leg_information1_encode(struct pri *ctrl, q931_call *call)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int res = 0;
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end = enc_etsi_diverting_leg_information1(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end = enc_qsig_diverting_leg_information1(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ default:
-+ return -1;
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */
-- res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */
-- res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_E163_E164;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */
-- pri_message(pri, "!! NsapEncodedNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */
-- if(rose_number_digits_decode(pri, call, comp->data, comp->len, value))
-- return -1;
-- value->npi = PRI_NPI_X121 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- pri_message(pri, "!! dataPartyNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_F69 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- pri_message(pri, "!! telexPartyNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
-- res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_PRIVATE;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_NATIONAL;
-- value->ton = PRI_TON_NATIONAL;
-- break;
-- default:
-- pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type);
-- return -1;
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG DivertingLegInformation2 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 2.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_diverting_leg_information2(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_DivertingLegInformation2;
-+ msg.invoke_id = get_invokeid(ctrl);
-+
-+ /* diversionCounter is the redirecting.count */
-+ msg.args.qsig.DivertingLegInformation2.diversion_counter = call->redirecting.count;
-+
-+ msg.args.qsig.DivertingLegInformation2.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-+
-+ /* divertingNr is the redirecting.from.number */
-+ msg.args.qsig.DivertingLegInformation2.diverting_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.diverting,
-+ &call->redirecting.from.number);
-+
-+ /* redirectingName is the redirecting.from.name */
-+ if (call->redirecting.from.name.valid) {
-+ msg.args.qsig.DivertingLegInformation2.redirecting_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.redirecting_name,
-+ &call->redirecting.from.name);
-+ }
-+
-+ if (1 < call->redirecting.count) {
-+ /* originalCalledNr is the redirecting.orig_called.number */
-+ msg.args.qsig.DivertingLegInformation2.original_called_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.original_called,
-+ &call->redirecting.orig_called.number);
-+
-+ msg.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1;
-+ if (call->redirecting.orig_called.number.valid) {
-+ msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.orig_reason);
-+ } else {
-+ msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
-+ QSIG_DIVERT_REASON_UNKNOWN;
- }
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
-- if(i < len)
-- pri_message(pri, "!! not all information is handled from Address component\n");
-- return res + 2;
-+
-+ /* originalCalledName is the redirecting.orig_called.name */
-+ if (call->redirecting.orig_called.name.valid) {
-+ msg.args.qsig.DivertingLegInformation2.original_called_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.original_called_name,
-+ &call->redirecting.orig_called.name);
-+ }
- }
-- while (0);
-
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI DivertingLegInformation2 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 2.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_diverting_leg_information2(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ struct rose_msg_invoke msg;
-
-- /* Fill in default values */
-- value->ton = PRI_TON_UNKNOWN;
-- value->npi = PRI_NPI_E163_E164;
-- value->pres = -1; /* Data is not available */
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_DivertingLegInformation2;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */
-- value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-- size = rose_address_decode(pri, call, comp->data, comp->len, value);
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-- return 2;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_NUMBER_NOT_AVAILABLE;
-- return 2;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */
-- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-- size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-- default:
-- pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type);
-- }
-- return -1;
-+ /* diversionCounter is the redirecting.count */
-+ msg.args.etsi.DivertingLegInformation2.diversion_counter = call->redirecting.count;
-+
-+ msg.args.etsi.DivertingLegInformation2.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-+
-+ /* divertingNr is the redirecting.from.number */
-+ msg.args.etsi.DivertingLegInformation2.diverting_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.DivertingLegInformation2.diverting,
-+ &call->redirecting.from.number);
-+
-+ if (1 < call->redirecting.count) {
-+ /* originalCalledNr is the redirecting.orig_called.number */
-+ msg.args.etsi.DivertingLegInformation2.original_called_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.DivertingLegInformation2.original_called,
-+ &call->redirecting.orig_called.number);
- }
-- while (0);
-
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+/*!
-+ * \internal
-+ * \brief Encode and queue the DivertingLegInformation2 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode diversion leg 2.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_diverting_leg_information2_encode(struct pri *ctrl, q931_call *call)
- {
-- int i = 0;
-- int diversion_counter;
-- int diversion_reason;
-- char origcalledname[50] = "", redirectingname[50] = "";
-- struct addressingdataelements_presentednumberunscreened divertingnr;
-- struct addressingdataelements_presentednumberunscreened originalcallednr;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-- memset(&divertingnr, 0, sizeof(divertingnr));
-- memset(&originalcallednr, 0, sizeof(originalcallednr));
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-- /* Data checks */
-- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid DivertingLegInformation2Type argument\n");
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end = enc_etsi_diverting_leg_information2(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end = enc_qsig_diverting_leg_information2(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ default:
- return -1;
- }
-+ if (!end) {
-+ return -1;
-+ }
-
-- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-- } else
-- len -= 2;
-+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
-+}
-
-- do {
-- /* diversionCounter stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do it diversionCounter is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, diversion_counter);
-- NEXT_COMPONENT(comp, i);
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG DivertingLegInformation3 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 3.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_diverting_leg_information3(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- /* diversionReason stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation2 component received\n");
-- ASN1_GET_INTEGER(comp, diversion_reason);
-- NEXT_COMPONENT(comp, i);
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- diversion_reason = redirectingreason_for_q931(pri, diversion_reason);
--
-- if(pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter);
-- pri_message(NULL, "Length of message is %d\n", len);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_DivertingLegInformation3;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- for(; i < len; NEXT_COMPONENT(comp, i)) {
-- GET_COMPONENT(comp, i, vdata, len);
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
-- call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1):
-- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr);
-- /* TODO: Fix indefinite length form hacks */
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (res < 0)
-- return -1;
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, " Received divertingNr '%s'\n", divertingnr.partyaddress);
-- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
-- }
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2):
-- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress);
-- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi);
-- }
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):
-- res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname));
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received RedirectingName '%s'\n", redirectingname);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):
-- res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5):
-- pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type);
-- break;
-- default:
-- if (comp->type == 0 && comp->len == 0) {
-- break; /* Found termination characters */
-- }
-- pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
-- return -1;
-- }
-- }
-+ /* redirecting.to.number.presentation also indicates if name presentation is allowed */
-+ if ((call->redirecting.to.number.presentation & PRI_PRES_RESTRICTION) == PRI_PRES_ALLOWED) {
-+ msg.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1; /* TRUE */
-
-- if (divertingnr.pres >= 0) {
-- call->redirectingplan = divertingnr.npi;
-- call->redirectingpres = divertingnr.pres;
-- call->redirectingreason = diversion_reason;
-- libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum));
-- pri_message(pri, " Received redirectingnum '%s' (%d)\n", call->redirectingnum, (int)call->redirectingnum[0]);
-+ /* redirectionName is the redirecting.to.name */
-+ if (call->redirecting.to.name.valid) {
-+ msg.args.qsig.DivertingLegInformation3.redirection_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation3.redirection_name,
-+ &call->redirecting.to.name);
- }
-- if (originalcallednr.pres >= 0) {
-- call->origcalledplan = originalcallednr.npi;
-- call->origcalledpres = originalcallednr.pres;
-- libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
-- pri_message(pri, " Received origcallednum '%s' (%d)\n", call->origcallednum, (int)call->origcallednum[0]);
-- }
-- libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
-- libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
-- return 0;
- }
-- while (0);
-
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
--
--static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
-+
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI DivertingLegInformation3 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 3.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_diverting_leg_information3(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
- {
-- int i = 0, j, compsp = 0;
-- struct rose_component *comp, *compstk[10];
-- unsigned char buffer[256];
-- int len = 253;
--
--#if 0 /* This is not required by specifications */
-- if (!strlen(call->callername)) {
-- return -1;
-+ struct rose_msg_invoke msg;
-+
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
- }
--#endif
-
-- buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- i++;
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */);
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
--
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Invoke component contents */
-- /* Invoke ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-- /* Operation Tag */
--
-- /* ROSE operationId component */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_DivertingLegInformation3;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- /* ROSE ARGUMENT component */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* ROSE DivertingLegInformation2.diversionCounter component */
-- /* Always is 1 because other isn't available in the current design */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
--
-- /* ROSE DivertingLegInformation2.diversionReason component */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason));
--
-- /* ROSE DivertingLegInformation2.divertingNr component */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
--
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Redirecting information always not screened */
--
-- switch(call->redirectingpres) {
-- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- if (call->redirectingnum && strlen(call->redirectingnum)) {
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* NPI of redirected number is not supported in the current design */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
-- if (j < 0)
-- return -1;
--
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- break;
-- }
-- /* fall through */
-- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- /* Don't know how to handle this */
-- case PRES_ALLOWED_NETWORK_NUMBER:
-- case PRES_PROHIB_NETWORK_NUMBER:
-- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- default:
-- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
-- case PRES_NUMBER_NOT_AVAILABLE:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
-- break;
-+ if ((call->redirecting.to.number.presentation & PRI_PRES_RESTRICTION) == PRI_PRES_ALLOWED) {
-+ msg.args.etsi.DivertingLegInformation3.presentation_allowed_indicator = 1; /* TRUE */
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-
-- /* ROSE DivertingLegInformation2.originalCalledNr component */
-- /* This information isn't supported by current design - duplicate divertingNr */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Redirecting information always not screened */
-- switch(call->redirectingpres) {
-- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- if (call->redirectingnum && strlen(call->redirectingnum)) {
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
--
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
-- if (j < 0)
-- return -1;
--
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- break;
-- }
-- /* fall through */
-- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- /* Don't know how to handle this */
-- case PRES_ALLOWED_NETWORK_NUMBER:
-- case PRES_PROHIB_NETWORK_NUMBER:
-- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- default:
-- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
-- case PRES_NUMBER_NOT_AVAILABLE:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
-- break;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode and queue the DivertingLegInformation3 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode diversion leg 3.
-+ * \param messagetype Q.931 message type to add facility ie to.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_diverting_leg_information3_encode(struct pri *ctrl, q931_call *call,
-+ int messagetype)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end = enc_etsi_diverting_leg_information3(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end = enc_qsig_diverting_leg_information3(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ default:
-+ return -1;
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- /* Fix length of stacked components */
-- while(compsp > 0) {
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ if (!end) {
-+ return -1;
- }
--
-- if (pri_call_apdu_queue(call, Q931_SETUP, buffer, i, NULL, NULL))
-- return -1;
--
-- return 0;
-+
-+ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
- }
-
--/* Send the rltThirdParty: Invoke */
--int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
-+/*!
-+ * \internal
-+ * \brief Encode the rltThirdParty invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param callwithid Call-ID information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_dms100_rlt_initiate_transfer(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const q931_call *callwithid)
- {
-- int i = 0;
-+ struct rose_msg_invoke msg;
-+
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_DMS100_RLT_ThirdParty;
-+ msg.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY;
-+ msg.args.dms100.RLT_ThirdParty.call_id = callwithid->rlt_call_id & 0xFFFFFF;
-+ msg.args.dms100.RLT_ThirdParty.reason = 0; /* unused, set to 129 */
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Send the rltThirdParty: Invoke.
-+ *
-+ * \note For PRI_SWITCH_DMS100 only.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param c1 Q.931 call leg 1
-+ * \param c2 Q.931 call leg 2
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rlt_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
-+{
- unsigned char buffer[256];
-- struct rose_component *comp = NULL, *compstk[10];
-- const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY;
-- q931_call *callwithid = NULL, *apdubearer = NULL;
-- int compsp = 0;
-+ unsigned char *end;
-+ q931_call *apdubearer;
-+ q931_call *callwithid;
-
- if (c2->transferable) {
- apdubearer = c1;
-@@ -906,279 +1374,415 @@
- } else if (c1->transferable) {
- apdubearer = c2;
- callwithid = c1;
-- } else
-+ } else {
- return -1;
-+ }
-
-- buffer[i++] = (Q932_PROTOCOL_ROSE);
-- buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
-+ end =
-+ enc_dms100_rlt_initiate_transfer(ctrl, buffer, buffer + sizeof(buffer),
-+ callwithid);
-+ if (!end) {
-+ return -1;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- /* Invoke ID is set to the operation ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
--
-- /* Operation Tag */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
--
-- /* Additional RLT invoke info - Octet 12 */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */
-- /* Reason for redirect - unused, set to 129 */
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
-+ if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, end - buffer, NULL)) {
- return -1;
-+ }
-
- if (q931_facility(apdubearer->pri, apdubearer)) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n",
-+ apdubearer->cr);
- return -1;
- }
- return 0;
- }
-
--static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c)
-+/*!
-+ * \internal
-+ * \brief Encode the rltOperationInd invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_dms100_rlt_transfer_ability(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end)
- {
-- int i = 0;
-- unsigned char buffer[256];
-- struct rose_component *comp = NULL, *compstk[10];
-- const unsigned char rlt_op_ind = RLT_OPERATION_IND;
-- int compsp = 0;
-+ struct rose_msg_invoke msg;
-
-- buffer[i++] = (Q932_PROTOCOL_ROSE); /* Note to self: DON'T set the EXT bit */
-- buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_DMS100_RLT_OperationInd;
-+ msg.invoke_id = ROSE_DMS100_RLT_OPERATION_IND;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- /* Invoke ID is set to the operation ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
--
-- /* Operation Tag - basically the same as the invoke ID tag */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
-- return -1;
-- else
-- return 0;
-+ return pos;
- }
-
--/* Sending callername information functions */
--static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
-+/*!
-+ * \internal
-+ * \brief Send the rltOperationInd: Invoke.
-+ *
-+ * \note For PRI_SWITCH_DMS100 only.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Q.931 call leg
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int add_dms100_transfer_ability_apdu(struct pri *ctrl, q931_call *call)
- {
-- int res = 0;
-- int i = 0;
- unsigned char buffer[256];
-- unsigned char namelen = 0;
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- int mymessage = 0;
-- static unsigned char op_tag[] = {
-- 0x2a, /* informationFollowing 42 */
-- 0x86,
-- 0x48,
-- 0xce,
-- 0x15,
-- 0x00,
-- 0x04
-- };
--
-- if (!strlen(c->callername)) {
-+ unsigned char *end;
-+
-+ end = enc_dms100_rlt_transfer_ability(ctrl, buffer, buffer + sizeof(buffer));
-+ if (!end) {
- return -1;
- }
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
-+}
-
-- if (pri->switchtype == PRI_SWITCH_QSIG) {
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+/*!
-+ * \internal
-+ * \brief Encode the NI2 InformationFollowing invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_ni2_information_following(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
- }
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_NI2_InformationFollowing;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.ni2.InformationFollowing.value = 0;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Invoke ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ return pos;
-+}
-
-- /* Operation Tag */
-- res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-- return -1;
-- i += res;
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CallingName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param name Name data which to encode name.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_calling_name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct q931_party_name *name)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (!cpe) {
-- if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
-- return -1;
-+ memset(&header, 0, sizeof(header));
-+ if (ctrl->switchtype == PRI_SWITCH_QSIG) {
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
- }
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallingName;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- /* Now the APDU that contains the information that needs sent.
-- * We can reuse the buffer since the queue function doesn't
-- * need it. */
-+ /* CallingName */
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CallingName.name, name);
-
-- i = 0;
-- namelen = strlen(c->callername);
-- if (namelen > 50) {
-- namelen = 50; /* truncate the name */
-- }
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ return pos;
-+}
-
-- if (pri->switchtype == PRI_SWITCH_QSIG) {
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+/*!
-+ * \internal
-+ * \brief Send caller name information.
-+ *
-+ * \note For PRI_SWITCH_NI2 and PRI_SWITCH_QSIG.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode name.
-+ * \param cpe TRUE if we are the CPE side.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int add_callername_facility_ies(struct pri *ctrl, q931_call *call, int cpe)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+ int mymessage;
-+
-+ if (!call->local_id.name.valid) {
-+ return 0;
- }
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
-+ if (ctrl->switchtype == PRI_SWITCH_NI2 && !cpe) {
-+ end = enc_ni2_information_following(ctrl, buffer, buffer + sizeof(buffer));
-+ if (!end) {
-+ return -1;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ if (pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL)) {
-+ return -1;
-+ }
-
-- /* Invoke ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ /*
-+ * We can reuse the buffer since the queue function doesn't
-+ * need it.
-+ */
-+ }
-
-- /* Operation ID: Calling name */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME);
--
-- res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen);
-- if (res < 0)
-+ /* CallingName is the local_id.name */
-+ end = enc_qsig_calling_name(ctrl, buffer, buffer + sizeof(buffer),
-+ &call->local_id.name);
-+ if (!end) {
- return -1;
-- i += res;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-
-- if (cpe)
-+ if (cpe) {
- mymessage = Q931_SETUP;
-- else
-+ } else {
- mymessage = Q931_FACILITY;
-+ }
-
-- if (pri_call_apdu_queue(c, mymessage, buffer, i, NULL, NULL))
-- return -1;
--
-- return 0;
-+ return pri_call_apdu_queue(call, mymessage, buffer, end - buffer, NULL);
- }
- /* End Callername */
-
- /* MWI related encode and decode functions */
--static void mwi_activate_encode_cb(void *data)
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG MWIActivate invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param req Served user setup request information.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_mwi_activate_message(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, struct pri_sr *req)
- {
-- return;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_MWIActivate;
-+ msg.invoke_id = get_invokeid(ctrl);
-+
-+ /* The called.number is the served user */
-+ q931_copy_number_to_rose(ctrl, &msg.args.qsig.MWIActivate.served_user_number,
-+ &req->called.number);
-+ /*
-+ * For now, we will just force the numbering plan to unknown to preserve
-+ * the original behaviour.
-+ */
-+ msg.args.qsig.MWIActivate.served_user_number.plan = 0; /* unknown */
-+
-+ msg.args.qsig.MWIActivate.basic_service = 1; /* speech */
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG MWIDeactivate invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param req Served user setup request information.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_mwi_deactivate_message(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, struct pri_sr *req)
- {
-- int i = 0;
-- unsigned char buffer[255] = "";
-- int destlen = strlen(req->called);
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- int res;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- if (destlen <= 0) {
-- return -1;
-- } else if (destlen > 20)
-- destlen = 20; /* Destination number cannot be greater then 20 digits */
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_MWIDeactivate;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* The called.number is the served user */
-+ q931_copy_number_to_rose(ctrl, &msg.args.qsig.MWIDeactivate.served_user_number,
-+ &req->called.number);
-+ /*
-+ * For now, we will just force the numbering plan to unknown to preserve
-+ * the original behaviour.
-+ */
-+ msg.args.qsig.MWIDeactivate.served_user_number.plan = 0; /* unknown */
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
-+ msg.args.qsig.MWIDeactivate.basic_service = 1; /* speech */
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ return pos;
-+}
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE);
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* PartyNumber */
-- res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
--
-- if (res < 0)
-+/*!
-+ * \brief Encode and queue the Q.SIG MWIActivate/MWIDeactivate invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg to queue message.
-+ * \param req Served user setup request information.
-+ * \param activate Nonzero to do the activate message.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int activate)
-+{
-+ unsigned char buffer[255];
-+ unsigned char *end;
-+
-+ if (!req->called.number.valid || !req->called.number.str[0]) {
- return -1;
-- i += res;
-+ }
-
-- /* Enumeration: basicService */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1 /* contents: Voice */);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ if (activate) {
-+ end = enc_qsig_mwi_activate_message(ctrl, buffer, buffer + sizeof(buffer), req);
-+ } else {
-+ end =
-+ enc_qsig_mwi_deactivate_message(ctrl, buffer, buffer + sizeof(buffer), req);
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
-- return pri_call_apdu_queue(call, Q931_SETUP, buffer, i, mwi_activate_encode_cb, NULL);
-+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
- }
- /* End MWI */
-
- /* EECT functions */
--int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
-+/*!
-+ * \internal
-+ * \brief Encode the NI2 InitiateTransfer invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode transfer information.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_ni2_initiate_transfer(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call)
- {
-- int i = 0;
-- int res = 0;
-- unsigned char buffer[255] = "";
-- short call_reference = c2->cr ^ 0x8000; /* Let's do the trickery to make sure the flag is correct */
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- static unsigned char op_tag[] = {
-- 0x2A,
-- 0x86,
-- 0x48,
-- 0xCE,
-- 0x15,
-- 0x00,
-- 0x08,
-- };
-+ struct rose_msg_invoke msg;
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_NI2_InitiateTransfer;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ /* Let's do the trickery to make sure the flag is correct */
-+ msg.args.ni2.InitiateTransfer.call_reference = call->cr ^ 0x8000;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ return pos;
-+}
-
-- res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-+/*!
-+ * \brief Start a 2BCT
-+ *
-+ * \note Called for PRI_SWITCH_NI2, PRI_SWITCH_LUCENT5E, and PRI_SWITCH_ATT4ESS
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param c1 Q.931 call leg 1
-+ * \param c2 Q.931 call leg 2
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int eect_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
-+{
-+ unsigned char buffer[255];
-+ unsigned char *end;
-+
-+ end = enc_ni2_initiate_transfer(ctrl, buffer, buffer + sizeof(buffer), c2);
-+ if (!end) {
- return -1;
-- i += res;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
-- if (res) {
-- pri_message(pri, "Could not queue APDU in facility message\n");
-+ if (pri_call_apdu_queue(c1, Q931_FACILITY, buffer, end - buffer, NULL)) {
-+ pri_message(ctrl, "Could not queue APDU in facility message\n");
- return -1;
- }
-
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
-
-- res = q931_facility(c1->pri, c1);
-- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
-+ if (q931_facility(c1->pri, c1)) {
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", c1->cr);
- return -1;
- }
-
-@@ -1187,1494 +1791,2316 @@
- /* End EECT */
-
- /* QSIG CF CallRerouting */
--int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason)
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CallRerouting invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Q.931 call leg.
-+ * \param calling Call rerouting/deflecting updated caller data.
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_call_rerouting(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, const struct q931_party_id *calling,
-+ const struct q931_party_redirecting *deflection, int subscription_option)
- {
--/*CallRerouting ::= OPERATION
-- -- Sent from the Served User PINX to the Rerouting PINX
-- ARGUMENT SEQUENCE
-- { reroutingReason DiversionReason,
-- originalReroutingReason [0] IMPLICIT DiversionReason OPTIONAL,
-- calledAddress Address,
-- diversionCounter INTEGER (1..15),
-- pSS1InfoElement PSS1InformationElement,
-- -- The basic call information elements Bearer capability, High layer compatibility, Low
-- -- layer compatibity, Progress indicator and Party category can be embedded in the
-- -- pSS1InfoElement in accordance with 6.5.3.1.5
-- lastReroutingNr [1] PresentedNumberUnscreened,
-- subscriptionOption [2] IMPLICIT SubscriptionOption,
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+ unsigned char *q931ie_pos;
-
-- callingPartySubaddress [3] PartySubaddress OPTIONAL,
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 2; /* rejectAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- callingNumber [4] PresentedNumberScreened,
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallRerouting;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- callingName [5] Name OPTIONAL,
-- originalCalledNr [6] PresentedNumberUnscreened OPTIONAL,
-- redirectingName [7] Name OPTIONAL,
-- originalCalledName [8] Name OPTIONAL,
-- extension CHOICE {
-- [9] IMPLICIT Extension ,
-- [10] IMPLICIT SEQUENCE OF Extension } OPTIONAL }
--*/
-+ msg.args.qsig.CallRerouting.rerouting_reason =
-+ redirectingreason_from_q931(ctrl, deflection->reason);
-
-- int i = 0, j;
-- int res = 0;
-- unsigned char buffer[255] = "";
-- int len = 253;
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- static unsigned char op_tag[] = {
-- 0x13,
-- };
-+ /* calledAddress is the passed in deflection->to address */
-+ q931_copy_address_to_rose(ctrl, &msg.args.qsig.CallRerouting.called, &deflection->to);
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ msg.args.qsig.CallRerouting.diversion_counter = deflection->count;
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* pSS1InfoElement */
-+ q931ie_pos = msg.args.qsig.CallRerouting.q931ie_contents;
-+ *q931ie_pos++ = 0x04; /* Bearer Capability IE */
-+ *q931ie_pos++ = 0x03; /* len */
-+ *q931ie_pos++ = 0x80 | call->transcapability; /* Rxed transfer capability. */
-+ *q931ie_pos++ = 0x90; /* circuit mode, 64kbit/s */
-+ *q931ie_pos++ = 0xa3; /* level1 protocol, a-law */
-+ *q931ie_pos++ = 0x95; /* locking shift to codeset 5 (national use) */
-+ *q931ie_pos++ = 0x32; /* Unknown ie */
-+ *q931ie_pos++ = 0x01; /* Unknown ie len */
-+ *q931ie_pos++ = 0x81; /* Unknown ie body */
-+ msg.args.qsig.CallRerouting.q931ie.length = q931ie_pos
-+ - msg.args.qsig.CallRerouting.q931ie_contents;
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
-+ /* lastReroutingNr is the passed in deflection->from.number */
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.last_rerouting, &deflection->from.number);
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ msg.args.qsig.CallRerouting.subscription_option = subscription_option;
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ /* callingNumber is the passed in calling->number */
-+ q931_copy_presented_number_screened_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.calling, &calling->number);
-
-- res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-- return -1;
-- i += res;
-+ /* callingPartySubaddress is the passed in calling->subaddress if valid */
-+ q931_copy_subaddress_to_rose(ctrl, &msg.args.qsig.CallRerouting.calling_subaddress,
-+ &calling->subaddress);
-
-- /* call rerouting argument */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ /* callingName is the passed in calling->name if valid */
-+ if (calling->name.valid) {
-+ msg.args.qsig.CallRerouting.calling_name_present = 1;
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CallRerouting.calling_name,
-+ &calling->name);
-+ }
-
-- /* reroutingReason DiversionReason */
-+ if (1 < deflection->count) {
-+ /* originalCalledNr is the deflection->orig_called.number */
-+ msg.args.qsig.CallRerouting.original_called_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.original_called,
-+ &deflection->orig_called.number);
-
-- if (reason) {
-- if (!strcasecmp(reason, "cfu"))
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1); /* cfu */
-- else if (!strcasecmp(reason, "cfb"))
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 2); /* cfb */
-- else if (!strcasecmp(reason, "cfnr"))
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3); /* cfnr */
-- } else {
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); /* unknown */
-+ msg.args.qsig.CallRerouting.original_rerouting_reason_present = 1;
-+ if (deflection->orig_called.number.valid) {
-+ msg.args.qsig.CallRerouting.original_rerouting_reason =
-+ redirectingreason_from_q931(ctrl, deflection->orig_reason);
-+ } else {
-+ msg.args.qsig.CallRerouting.original_rerouting_reason =
-+ QSIG_DIVERT_REASON_UNKNOWN;
-+ }
-+
-+ /* originalCalledName is the deflection->orig_called.name */
-+ if (deflection->orig_called.name.valid) {
-+ msg.args.qsig.CallRerouting.original_called_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.original_called_name,
-+ &deflection->orig_called.name);
-+ }
- }
-
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- /* calledAddress Address */
-- /* explicit sequence tag for Address */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* implicit choice public party number tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* type of public party number = unknown */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
-- /* NumberDigits of public party number */
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, (char*)dest, strlen(dest));
-- if (j < 0)
-- return -1;
-+ return pos;
-+}
-
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI CallRerouting invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Q.931 call leg.
-+ * \param calling Call rerouting/deflecting updated caller data.
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_call_rerouting(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, const struct q931_party_id *calling,
-+ const struct q931_party_redirecting *deflection, int subscription_option)
-+{
-+ struct rose_msg_invoke msg;
-+ unsigned char *q931ie_pos;
-
-- /* diversionCounter INTEGER (1..15) */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /* pSS1InfoElement */
-- ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION | ASN1_TAG_0 ), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- buffer[i++] = (0x04); /* Bearer Capability IE */
-- buffer[i++] = (0x03); /* len */
-- buffer[i++] = (0x80); /* ETSI Standard, Speech */
-- buffer[i++] = (0x90); /* circuit mode, 64kbit/s */
-- buffer[i++] = (0xa3); /* level1 protocol, a-law */
-- buffer[i++] = (0x95); /* locking shift to codeset 5 (national use) */
-- buffer[i++] = (0x32); /* Unknown ie */
-- buffer[i++] = (0x01); /* Unknown ie len */
-- buffer[i++] = (0x81); /* Unknown ie body */
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_CallRerouting;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- /* lastReroutingNr [1]*/
-- /* implicit optional lastReroutingNr tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ msg.args.etsi.CallRerouting.rerouting_reason =
-+ redirectingreason_from_q931(ctrl, deflection->reason);
-
-- /* implicit choice presented number unscreened tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ /* calledAddress is the passed in deflection->to address */
-+ q931_copy_address_to_rose(ctrl, &msg.args.etsi.CallRerouting.called_address,
-+ &deflection->to);
-
-- /* implicit choice public party number tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* type of public party number = unknown */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, original?(char*)original:c->callednum, original?strlen(original):strlen(c->callednum));
-- if (j < 0)
-- return -1;
-+ msg.args.etsi.CallRerouting.rerouting_counter = deflection->count;
-
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* q931InfoElement */
-+ q931ie_pos = msg.args.etsi.CallRerouting.q931ie_contents;
-+ *q931ie_pos++ = 0x04; /* Bearer Capability IE */
-+ *q931ie_pos++ = 0x03; /* len */
-+ *q931ie_pos++ = 0x80 | call->transcapability; /* Rxed transfer capability. */
-+ *q931ie_pos++ = 0x90; /* circuit mode, 64kbit/s */
-+ *q931ie_pos++ = 0xa3; /* level1 protocol, a-law */
-+ msg.args.etsi.CallRerouting.q931ie.length = q931ie_pos
-+ - msg.args.etsi.CallRerouting.q931ie_contents;
-
-- /* subscriptionOption [2]*/
-- /* implicit optional lastReroutingNr tag */
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* noNotification */
-+ /* lastReroutingNr is the passed in deflection->from.number */
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.CallRerouting.last_rerouting, &deflection->from.number);
-
-- /* callingNumber [4]*/
-- /* implicit optional callingNumber tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ msg.args.etsi.CallRerouting.subscription_option = subscription_option;
-
-- /* implicit choice presented number screened tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ /* callingPartySubaddress is the passed in calling->subaddress if valid */
-+ q931_copy_subaddress_to_rose(ctrl, &msg.args.etsi.CallRerouting.calling_subaddress,
-+ &calling->subaddress);
-
-- /* implicit choice presentationAllowedAddress tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* type of public party number = subscriber number */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 4);
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, c->callernum, strlen(c->callernum));
-- if (j < 0)
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ return pos;
-+}
-
-- /* Screeening Indicator network provided */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3);
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI CallDeflection invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Q.931 call leg.
-+ * \param deflection Call deflection address.
-+ *
-+ * \note
-+ * deflection is the new called number and must always be present.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_call_deflection(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, const struct q931_party_id *deflection)
-+{
-+ struct rose_msg_invoke msg;
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /**/
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_CallDeflection;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* deflectionAddress is the passed in deflection->to address */
-+ q931_copy_address_to_rose(ctrl, &msg.args.etsi.CallDeflection.deflection,
-+ deflection);
-
-- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
-- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-+ msg.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1;
-+ switch (deflection->number.presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ msg.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 1;
-+ break;
-+ default:
-+ case PRI_PRES_UNAVAILABLE:
-+ case PRI_PRES_RESTRICTED:
-+ break;
-+ }
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode and queue the CallRerouting/CallDeflection message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_reroute_request_encode(struct pri *ctrl, q931_call *call,
-+ const struct q931_party_id *caller, const struct q931_party_redirecting *deflection,
-+ int subscription_option)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ if (!caller) {
-+ /*
-+ * We are deflecting an incoming call back to the network.
-+ * Therefore, the Caller-ID is the remote party.
-+ */
-+ caller = &call->remote_id;
-+ }
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ end =
-+ enc_etsi_call_deflection(ctrl, buffer, buffer + sizeof(buffer), call,
-+ &deflection->to);
-+ } else {
-+ end =
-+ enc_etsi_call_rerouting(ctrl, buffer, buffer + sizeof(buffer), call,
-+ caller, deflection, subscription_option);
-+ }
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_call_rerouting(ctrl, buffer, buffer + sizeof(buffer), call, caller,
-+ deflection, subscription_option);
-+ break;
-+ default:
- return -1;
- }
-+ if (!end) {
-+ return -1;
-+ }
-
-- /* Remember that if we queue a facility IE for a facility message we
-- * have to explicitly send the facility message ourselves */
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
-+}
-
-- res = q931_facility(c->pri, c);
-- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
-+/*!
-+ * \brief Send the CallRerouting/CallDeflection message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int send_reroute_request(struct pri *ctrl, q931_call *call,
-+ const struct q931_party_id *caller, const struct q931_party_redirecting *deflection,
-+ int subscription_option)
-+{
-+ if (!deflection->to.number.str[0]) {
-+ /* Must have a deflect to number. That is the point of deflection. */
- return -1;
- }
-+ if (rose_reroute_request_encode(ctrl, call, caller, deflection, subscription_option)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for CallRerouting/CallDeflection message.\n");
-+ return -1;
-+ }
-
- return 0;
- }
-+
-+/*!
-+ * \brief Send the Q.SIG CallRerouting invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Q.931 call leg.
-+ * \param dest Destination number.
-+ * \param original Original called number.
-+ * \param reason Rerouting reason: cfu, cfb, cfnr
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int qsig_cf_callrerouting(struct pri *ctrl, q931_call *call, const char *dest,
-+ const char *original, const char *reason)
-+{
-+ struct q931_party_redirecting reroute;
-+
-+ q931_party_redirecting_init(&reroute);
-+
-+ /* Rerouting to the dest number. */
-+ reroute.to.number.valid = 1;
-+ reroute.to.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ reroute.to.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ libpri_copy_string(reroute.to.number.str, dest, sizeof(reroute.to.number.str));
-+
-+ /* Rerouting from the original number. */
-+ if (original) {
-+ reroute.from.number.valid = 1;
-+ reroute.from.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ libpri_copy_string(reroute.from.number.str, original, sizeof(reroute.from.number.str));
-+ } else {
-+ q931_party_address_to_id(&reroute.from, &call->called);
-+ }
-+ reroute.from.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+
-+ /* Decode the rerouting reason. */
-+ reroute.reason = PRI_REDIR_UNKNOWN;
-+ if (!reason) {
-+ /* No reason for rerouting given. */
-+ } else if (!strcasecmp(reason, "cfu")) {
-+ reroute.reason = PRI_REDIR_UNCONDITIONAL;
-+ } else if (!strcasecmp(reason, "cfb")) {
-+ reroute.reason = PRI_REDIR_FORWARD_ON_BUSY;
-+ } else if (!strcasecmp(reason, "cfnr")) {
-+ reroute.reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ }
-+
-+ reroute.count = (call->redirecting.count < PRI_MAX_REDIRECTS)
-+ ? call->redirecting.count + 1 : PRI_MAX_REDIRECTS;
-+
-+ if (!call->redirecting.orig_called.number.valid) {
-+ /*
-+ * Since we do not already have an originally called party, we
-+ * must either be the first redirected to party or this call
-+ * has not been redirected before.
-+ *
-+ * Preserve who redirected to us as the originally called party.
-+ */
-+ reroute.orig_called = call->redirecting.from;
-+ reroute.orig_reason = call->redirecting.reason;
-+ } else {
-+ reroute.orig_called = call->redirecting.orig_called;
-+ reroute.orig_reason = call->redirecting.orig_reason;
-+ }
-+
-+ return send_reroute_request(ctrl, call, NULL, &reroute, 0 /* noNotification */);
-+}
- /* End QSIG CC-CallRerouting */
-
--static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_ie *ie)
-+/*
-+ * From Mantis issue 7778 description: (ETS 300 258, ISO 13863)
-+ * After both legs of the call are setup and Asterisk has a successful "tromboned" or bridged call ...
-+ * Asterisk sees both 'B' channels (from trombone) are on same PRI/technology and initiates "Path Replacement" events
-+ * a. Asterisk sends "Transfer Complete" messages to both call legs
-+ * b. QSIG Switch sends "PathReplacement" message on one of the legs (random 1-10sec timer expires - 1st leg to send is it!)
-+ * c. Asterisk rebroadcasts "PathReplacement" message to other call leg
-+ * d. QSIG Switch sends "Disconnect" message on one of the legs (same random timer sequence as above)
-+ * e. Asterisk rebroadcasts "Disconnect" message to other call leg
-+ * f. QSIG Switch disconnects Asterisk call legs - callers are now within QSIG switch
-+ *
-+ * Just need to resend the message to the other tromboned leg of the call.
-+ */
-+static int anfpr_pathreplacement_respond(struct pri *ctrl, q931_call *call, q931_ie *ie)
- {
- int res;
--
-- res = pri_call_apdu_queue_cleanup(call->bridged_call);
-- if (res) {
-- pri_message(pri, "Could not Clear queue ADPU\n");
-- return -1;
-- }
--
-+
-+ pri_call_apdu_queue_cleanup(call->bridged_call);
-+
- /* Send message */
-- res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL, NULL);
-+ res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL);
- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-- return -1;
-+ pri_message(ctrl, "Could not queue ADPU in facility message\n");
-+ return -1;
- }
--
-+
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
--
-+
- res = q931_facility(call->bridged_call->pri, call->bridged_call);
- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", call->bridged_call->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n",
-+ call->bridged_call->cr);
- return -1;
- }
-
- return 0;
- }
-+
- /* AFN-PR */
--int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
-+/*!
-+ * \brief Start a Q.SIG path replacement.
-+ *
-+ * \note Called for PRI_SWITCH_QSIG
-+ *
-+ * \note Did all the tests to see if we're on the same PRI and
-+ * are on a compatible switchtype.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param c1 Q.931 call leg 1
-+ * \param c2 Q.931 call leg 2
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int anfpr_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
- {
-- /* Did all the tests to see if we're on the same PRI and
-- * are on a compatible switchtype */
-- /* TODO */
-- int i = 0;
-- int res = 0;
-- unsigned char buffer[255] = "";
-- unsigned short call_reference = c2->cr;
-- struct rose_component *comp = NULL, *compstk[10];
-- unsigned char buffer2[255] = "";
-- int compsp = 0;
-- static unsigned char op_tag[] = {
-- 0x0C,
-- };
--
-- /* Channel 1 */
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
--
-- res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-+ unsigned char buffer[255];
-+ unsigned char *pos;
-+ unsigned char *end;
-+ int res;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ end = buffer + sizeof(buffer);
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 2; /* rejectAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, buffer, end, &header);
-+ if (!pos) {
- return -1;
-- i += res;
--
-- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- buffer[i++] = (0x0a);/* Enumeration endDesignation */
-- buffer[i++] = (0x01);/* Len */
-- buffer[i++] = (0x00);/* primaryEnd */
-- buffer[i++] = (0x81);/* redirectionNumber = presentationRestricted */
-- buffer[i++] = (0x00);/* Len */
-- buffer[i++] = (0x0a);/* Enumeration callStatus */
-- buffer[i++] = (0x01);/* Len */
-- buffer[i++] = (0x01);/* alerting */
-+ }
-
-- /*
-- * Where does this element come from? It is not in Q.SIG ECMA-178.
-- * We send this but we will not accept it.
-- * This seems to be a cut and paste error from eect_initiate_transfer().
-- */
-- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallTransferComplete;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.CallTransferComplete.end_designation = 0; /* primaryEnd */
-+ msg.args.qsig.CallTransferComplete.redirection.presentation = 1; /* presentationRestricted */
-+ msg.args.qsig.CallTransferComplete.call_status = 1; /* alerting */
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+ if (!pos) {
-+ return -1;
-+ }
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
-+ res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, pos - buffer, NULL);
- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-+ pri_message(ctrl, "Could not queue ADPU in facility message\n");
- return -1;
- }
--
-+
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
--
-+
- res = q931_facility(c1->pri, c1);
- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", c1->cr);
- return -1;
- }
--
-- /* Channel 2 */
-- i = 0;
-- res = 0;
-- compsp = 0;
--
-- buffer2[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer2, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer2, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer2, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer2, i);
--
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer2, i, 2); /* reject */
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer2, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer2, i, get_invokeid(pri));
--
-- res = asn1_string_encode(ASN1_INTEGER, &buffer2[i], sizeof(buffer2)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-+
-+ /* Reuse the previous message header */
-+ pos = facility_encode_header(ctrl, buffer, end, &header);
-+ if (!pos) {
- return -1;
-- i += res;
--
-- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer2, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- buffer2[i++] = (0x0a);/* Enumeration endDesignation */
-- buffer2[i++] = (0x01);/* Len */
-- buffer2[i++] = (0x01);/* secondaryEnd */
-- buffer2[i++] = (0x81);/* redirectionNumber = presentationRestricted */
-- buffer2[i++] = (0x00);/* Len */
-- buffer2[i++] = (0x0a);/* Enumeration callStatus */
-- buffer2[i++] = (0x01);/* Len */
-- buffer2[i++] = (0x01);/* alerting */
-+ }
-
-- /*
-- * Where does this element come from? It is not in Q.SIG ECMA-178.
-- * We send this but we will not accept it.
-- * This seems to be a cut and paste error from eect_initiate_transfer().
-- */
-- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer2, i, call_reference);
-+ /* Update the previous message */
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.CallTransferComplete.end_designation = 1; /* secondaryEnd */
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+ if (!pos) {
-+ return -1;
-+ }
-
-- ASN1_FIXUP(compstk, compsp, buffer2, i);
-- ASN1_FIXUP(compstk, compsp, buffer2, i);
--
--
-- res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer2, i, NULL, NULL);
-+ res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer, pos - buffer, NULL);
- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-+ pri_message(ctrl, "Could not queue ADPU in facility message\n");
- return -1;
- }
--
-+
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
--
-+
- res = q931_facility(c2->pri, c2);
- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", c2->cr);
- return -1;
- }
--
-+
- return 0;
- }
- /* End AFN-PR */
-
- /* AOC */
--static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI AOCEChargingUnit invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param chargedunits Number of units charged to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_aoce_charging_unit(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, long chargedunits)
- {
-- int chargingcase = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
-- int pos1 = 0;
-+ struct rose_msg_invoke msg;
-
-- if (pri->debug & PRI_DEBUG_AOC)
-- dump_apdu (pri, data, len);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- do {
-- GET_COMPONENT(comp, pos1, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n");
-- ASN1_GET_INTEGER(comp, chargingcase);
-- if (chargingcase >= 0 && chargingcase <= 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n",
-- call->ds1no, call->channelno, call->cr, chargingcase);
-- } else {
-- pri_message(pri, "!! unkown AOC ChargingCase: 0x%02X", chargingcase);
-- chargingcase = -1;
-- }
-- NEXT_COMPONENT(comp, pos1);
-- } while (pos1 < len);
-- if (pos1 < len) {
-- pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
-- dump_apdu (pri, data, len);
-- return -1; /* Aborted before */
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_AOCEChargingUnit;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.etsi.AOCEChargingUnit.type = 1; /* charging_unit */
-+ if (chargedunits <= 0) {
-+ msg.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1;
-+ } else {
-+ msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1;
-+ msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].
-+ number_of_units = chargedunits;
- }
-- return 0;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
--
-
--static int aoc_aoce_charging_unit_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
-+/*!
-+ * \internal
-+ * \brief Send the ETSI AOCEChargingUnit invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode AOC.
-+ * \param chargedunits Number of units charged to encode.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int aoc_aoce_charging_unit_encode(struct pri *ctrl, q931_call *call,
-+ long chargedunits)
- {
-- long chargingunits = 0, chargetype = -1, temp, chargeIdentifier = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp1 = NULL, *comp2 = NULL, *comp3 = NULL;
-- int pos1 = 0, pos2, pos3, sublen2, sublen3;
-- struct addressingdataelements_presentednumberunscreened chargednr;
-+ unsigned char buffer[255];
-+ unsigned char *end;
-
-- if (pri->debug & PRI_DEBUG_AOC)
-- dump_apdu (pri, data, len);
-+ /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
-
-- do {
-- GET_COMPONENT(comp1, pos1, vdata, len); /* AOCEChargingUnitInfo */
-- CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but Received 0x%02X\n");
-- SUB_COMPONENT(comp1, pos1);
-- GET_COMPONENT(comp1, pos1, vdata, len);
-- switch (comp1->type) {
-- case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR): /* specificChargingUnits */
-- sublen2 = comp1->len;
-- pos2 = pos1;
-- comp2 = comp1;
-- SUB_COMPONENT(comp2, pos2);
-- do {
-- GET_COMPONENT(comp2, pos2, vdata, len);
-- switch (comp2->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* RecordedUnitsList (0xA1) */
-- SUB_COMPONENT(comp2, pos2);
-- GET_COMPONENT(comp2, pos2, vdata, len);
-- CHECK_COMPONENT(comp2, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but received 0x02%X\n"); /* RecordedUnits */
-- sublen3 = pos2 + comp2->len;
-- pos3 = pos2;
-- comp3 = comp2;
-- SUB_COMPONENT(comp3, pos3);
-- do {
-- GET_COMPONENT(comp3, pos3, vdata, len);
-- switch (comp3->type) {
-- case ASN1_INTEGER: /* numberOfUnits */
-- ASN1_GET_INTEGER(comp3, temp);
-- chargingunits += temp;
-- case ASN1_NULL: /* notAvailable */
-- break;
-- default:
-- pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnits\n", comp3->type);
-- }
-- NEXT_COMPONENT(comp3, pos3);
-- } while (pos3 < sublen3);
-- if (pri->debug & PRI_DEBUG_AOC)
-- pri_message(pri, "Channel %d/%d, Call %d - received AOC-E charging: %i unit%s\n",
-- call->ds1no, call->channelno, call->cr, chargingunits, (chargingunits == 1) ? "" : "s");
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* AOCEBillingID (0xA2) */
-- SUB_COMPONENT(comp2, pos2);
-- GET_COMPONENT(comp2, pos2, vdata, len);
-- ASN1_GET_INTEGER(comp2, chargetype);
-- pri_message(pri, "!! not handled: Channel %d/%d, Call %d - received AOC-E billing ID: %i\n",
-- call->ds1no, call->channelno, call->cr, chargetype);
-- break;
-- default:
-- pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnitsList\n", comp2->type);
-- }
-- NEXT_COMPONENT(comp2, pos2);
-- } while (pos2 < sublen2);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* freeOfCharge (0x81) */
-- if (pri->debug & PRI_DEBUG_AOC)
-- pri_message(pri, "Channel %d/%d, Call %d - received AOC-E free of charge\n", call->ds1no, call->channelno, call->cr);
-- chargingunits = 0;
-- break;
-- default:
-- pri_message(pri, "!! Invalid AOC-E specificChargingUnits. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type);
-- }
-- NEXT_COMPONENT(comp1, pos1);
-- GET_COMPONENT(comp1, pos1, vdata, len); /* get optional chargingAssociation. will 'break' when reached end of structure */
-- switch (comp1->type) {
-- /* TODO: charged number is untested - please report! */
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* chargedNumber (0xA0) */
-- if(rose_presented_number_unscreened_decode(pri, call, comp1->data, comp1->len, &chargednr) != 0)
-- return -1;
-- pri_message(pri, "!! not handled: Received ChargedNr '%s' \n", chargednr.partyaddress);
-- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", chargednr.ton, chargednr.pres, chargednr.npi);
-- break;
-- case ASN1_INTEGER:
-- ASN1_GET_INTEGER(comp1, chargeIdentifier);
-- break;
-- default:
-- pri_message(pri, "!! Invalid AOC-E chargingAssociation. Expected Object Identifier (0xA0) or Integer (0x02) but received 0x%02X\n", comp1->type);
-- }
-- NEXT_COMPONENT(comp1, pos1);
-- } while (pos1 < len);
-+ end =
-+ enc_etsi_aoce_charging_unit(ctrl, buffer, buffer + sizeof(buffer), chargedunits);
-+ if (!end) {
-+ return -1;
-+ }
-
-- if (pos1 < len) {
-- pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
-- dump_apdu (pri, data, len);
-- return -1; /* oops - aborted before */
-+ /* Remember that if we queue a facility IE for a facility message we
-+ * have to explicitly send the facility message ourselves */
-+ if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL)
-+ || q931_facility(call->pri, call)) {
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", call->cr);
-+ return -1;
- }
-- call->aoc_units = chargingunits;
--
-+
- return 0;
- }
-+/* End AOC */
-
--static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits)
-+/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CallTransferComplete invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode call transfer.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_call_transfer_complete(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call, int call_status)
- {
-- /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
-- int i = 0, res = 0, compsp = 0;
-- unsigned char buffer[255] = "";
-- struct rose_component *comp = NULL, *compstk[10];
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- /* ROSE protocol (0x91)*/
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /* ROSE Component (0xA1,len)*/
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallTransferComplete;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.CallTransferComplete.end_designation = 0; /* primaryEnd */
-
-- /* ROSE invokeId component (0x02,len,id)*/
-- ASN1_ADD_WORDCOMP(comp, INVOKE_IDENTIFIER, buffer, i, ++pri->last_invoke);
-+ /* redirectionNumber is the local_id.number */
-+ q931_copy_presented_number_screened_to_rose(ctrl,
-+ &msg.args.qsig.CallTransferComplete.redirection, &call->local_id.number);
-
-- /* ROSE operationId component (0x02,0x01,0x24)*/
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_AOC_AOCE_CHARGING_UNIT);
-+ /* redirectionName is the local_id.name */
-+ if (call->local_id.name.valid) {
-+ msg.args.qsig.CallTransferComplete.redirection_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.CallTransferComplete.redirection_name,
-+ &call->local_id.name);
-+ }
-
-- /* AOCEChargingUnitInfo (0x30,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ if (call_status) {
-+ msg.args.qsig.CallTransferComplete.call_status = 1; /* alerting */
-+ }
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- if (chargedunits > 0) {
-- /* SpecificChargingUnits (0x30,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ return pos;
-+}
-
-- /* RecordedUnitsList (0xA1,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- /* RecordedUnits (0x30,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- /* NumberOfUnits (0x02,len,charge) */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, chargedunits);
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI EctInform invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode inform message.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_ect_inform(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int call_status)
-+{
-+ struct rose_msg_invoke msg;
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- } else {
-- /* freeOfCharge (0x81,0) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (pri->debug & PRI_DEBUG_AOC)
-- dump_apdu (pri, buffer, i);
--
-- /* code below is untested */
-- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
-- if (res) {
-- pri_message(pri, "Could not queue APDU in facility message\n");
-- return -1;
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_EctInform;
-+ msg.invoke_id = get_invokeid(ctrl);
-+
-+ if (!call_status) {
-+ msg.args.etsi.EctInform.status = 1;/* active */
-+
-+ /*
-+ * EctInform(active) contains the redirectionNumber
-+ * redirectionNumber is the local_id.number
-+ */
-+ msg.args.etsi.EctInform.redirection_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.EctInform.redirection, &call->local_id.number);
- }
-
-- /* Remember that if we queue a facility IE for a facility message we
-- * have to explicitly send the facility message ourselves */
-- res = q931_facility(c->pri, c);
-- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode and queue the CallTransferComplete/EctInform invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode call transfer.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_call_transfer_complete_encode(struct pri *ctrl, q931_call *call,
-+ int call_status)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end =
-+ enc_etsi_ect_inform(ctrl, buffer, buffer + sizeof(buffer), call, call_status);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_call_transfer_complete(ctrl, buffer, buffer + sizeof(buffer), call,
-+ call_status);
-+ break;
-+ default:
- return -1;
- }
-+ if (!end) {
-+ return -1;
-+ }
-
-- return 0;
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
- }
--/* End AOC */
-
--static int rose_calling_name_decode(struct pri *pri, q931_call *call, struct rose_component *choice, int len)
-+/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CalledName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param name Name data which to encode name.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_called_name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct q931_party_name *name)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = choice->data;
-- int characterSet = 1;
-- switch (choice->type) {
-- case ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE:
-- memcpy(call->callername, choice->data, choice->len);
-- call->callername[choice->len] = 0;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received simple calling name '%s'\n", call->callername);
-- return 0;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- case ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED:
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if nameData is of type 0x%x\n");
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- NEXT_COMPONENT(comp, i);
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, characterSet);
-- }
-- while (0);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CalledName;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received extended calling name '%s', characterset %d\n", call->callername, characterSet);
-- return 0;
-- case ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE:
-- case ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED:
-- case ROSE_NAME_PRESENTATION_RESTRICTED_NULL:
-- case ROSE_NAME_NOT_AVAIL:
-- default:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Do not handle argument of type 0x%X\n", choice->type);
-- return -1;
-- }
-+ /* CalledName */
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CalledName.name, name);
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
--/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
-
--static int rose_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Encode and queue the Q.SIG CalledName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode name.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_called_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-+ /* CalledName is the local_id.name */
-+ end = enc_qsig_called_name(ctrl, buffer, buffer + sizeof(buffer),
-+ &call->local_id.name);
-+ if (!end) {
-+ return -1;
-+ }
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
-+}
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG ConnectedName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param name Name data which to encode name.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_connected_name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct q931_party_name *name)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
-- size = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_E163_E164;
-- break;
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
-- pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_X121 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- break;
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_ConnectedName;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
-- pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_F69 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- break;
-+ /* ConnectedName */
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.ConnectedName.name, name);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
-- size = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_PRIVATE;
-- break;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
-- pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_NATIONAL;
-- value->ton = PRI_TON_NATIONAL;
-- break;
-+ return pos;
-+}
-
-- default:
-- pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
-- return -1;
-- }
-- ASN1_FIXUP_LEN(comp, size);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
-- return size;
-+/*!
-+ * \internal
-+ * \brief Encode and queue the Q.SIG ConnectedName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode name.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_connected_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ /* ConnectedName is the local_id.name */
-+ end = enc_qsig_connected_name(ctrl, buffer, buffer + sizeof(buffer),
-+ &call->local_id.name);
-+ if (!end) {
-+ return -1;
- }
-- while (0);
-
-- return -1;
-+ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
- }
-
--
--static int rose_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+/*!
-+ * \brief Put the APDU on the call queue.
-+ *
-+ * \param call Call to enqueue message.
-+ * \param messagetype Q.931 message type.
-+ * \param apdu Facility ie contents buffer.
-+ * \param apdu_len Length of the contents buffer.
-+ * \param response Sender supplied information to handle APDU response messages.
-+ * NULL if don't care about responses.
-+ *
-+ * \note
-+ * Only APDU messages with an invoke component can supply a response pointer.
-+ * If any other APDU messages supply a response pointer then aliasing of the
-+ * invoke_id can occur.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ struct apdu_event *cur = NULL;
-+ struct apdu_event *new_event = NULL;
-
-- int scrind = -1;
--
-- do {
-- /* Party Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- size = rose_party_number_decode(pri, call, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value);
-- if (size < 0)
-+ if (!call || !messagetype || !apdu
-+ || apdu_len < 1 || sizeof(new_event->apdu) < apdu_len) {
-+ return -1;
-+ }
-+ switch (messagetype) {
-+ case Q931_FACILITY:
-+ break;
-+ default:
-+ if (q931_is_dummy_call(call)) {
-+ pri_error(call->pri, "!! Cannot send %s message on dummy call reference.\n",
-+ msg2str(messagetype));
- return -1;
-- comp->len = size;
-- NEXT_COMPONENT(comp, i);
-+ }
-+ break;
-+ }
-
-- /* Screening Indicator */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, scrind);
-- // Todo: scrind = screeningindicator_for_q931(pri, scrind);
-- NEXT_COMPONENT(comp, i);
-+ new_event = calloc(1, sizeof(*new_event));
-+ if (!new_event) {
-+ pri_error(call->pri, "!! Malloc failed!\n");
-+ return -1;
-+ }
-
-- value->scrind = scrind;
-+ /* Fill in the APDU event */
-+ new_event->message = messagetype;
-+ if (response) {
-+ new_event->response = *response;
-+ }
-+ new_event->call = call;
-+ new_event->apdu_len = apdu_len;
-+ memcpy(new_event->apdu, apdu, apdu_len);
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
--
-- return i-2; // We do not have a sequence header here.
-+ /* Append APDU event to the end of the list. */
-+ if (call->apdus) {
-+ for (cur = call->apdus; cur->next; cur = cur->next) {
-+ }
-+ cur->next = new_event;
-+ } else {
-+ call->apdus = new_event;
- }
-- while (0);
-
-- return -1;
-+ return 0;
- }
-
--
--static int rose_presented_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
-+void pri_call_apdu_queue_cleanup(q931_call *call)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ struct apdu_event *cur_event;
-+ struct apdu_event *free_event;
-
-- /* Fill in default values */
-- value->ton = PRI_TON_UNKNOWN;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->pres = -1; /* Data is not available */
-+ if (call) {
-+ cur_event = call->apdus;
-+ call->apdus = NULL;
-+ while (cur_event) {
-+ if (cur_event->response.callback) {
-+ /* Indicate to callback that the APDU is being cleaned up. */
-+ cur_event->response.callback(APDU_CALLBACK_REASON_CLEANUP, call->pri,
-+ call, cur_event, NULL);
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ /* Stop any response timeout. */
-+ pri_schedule_del(call->pri, cur_event->timer);
-+ }
-+ free_event = cur_event;
-+ cur_event = cur_event->next;
-+ free(free_event);
-+ }
-+ }
-+}
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len);
-- value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-+/*!
-+ * \internal
-+ * \brief Find an outstanding APDU with the given invoke id.
-+ *
-+ * \param call Call to find APDU.
-+ * \param invoke_id Invoke id to match outstanding APDUs in queue.
-+ *
-+ * \retval apdu_event if found.
-+ * \retval NULL if not found.
-+ */
-+static struct apdu_event *pri_call_apdu_find(struct q931_call *call, int invoke_id)
-+{
-+ struct apdu_event *apdu;
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len);
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-- return 2;
-+ for (apdu = call->apdus; apdu; apdu = apdu->next) {
-+ /*
-+ * Note: The APDU cannot be sent and still in the queue without a
-+ * callback and timeout timer active. Therefore, an invoke_id of
-+ * zero is valid and not just the result of a memset().
-+ */
-+ if (apdu->response.invoke_id == invoke_id && apdu->sent) {
-+ break;
-+ }
-+ }
-+ return apdu;
-+}
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_NUMBER_NOT_AVAILABLE;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
-- return 2;
-+/*!
-+ * \brief Delete the given APDU event from the given call.
-+ *
-+ * \param call Call to remove the APDU.
-+ * \param doomed APDU event to delete.
-+ *
-+ * \return Nothing
-+ */
-+void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed)
-+{
-+ struct apdu_event **prev;
-+ struct apdu_event *cur;
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len);
-- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-+ /* Find APDU in list. */
-+ for (prev = &call->apdus, cur = call->apdus;
-+ cur;
-+ prev = &cur->next, cur = cur->next) {
-+ if (cur == doomed) {
-+ /* Stop any response timeout. */
-+ pri_schedule_del(call->pri, cur->timer);
-
-- default:
-- pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->type);
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+ free(cur);
-+ break;
- }
-- return -1;
- }
-- while (0);
--
-- return -1;
- }
-
--
--static int rose_call_transfer_complete_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+/*! \note Only called when sending the SETUP message. */
-+int pri_call_add_standard_apdus(struct pri *ctrl, q931_call *call)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-+ if (!ctrl->sendfacility) {
-+ return 0;
-+ }
-
-- int end_designation = 0;
-- struct addressingdataelements_presentednumberscreened redirection_number;
-- char redirection_name[50] = "";
-- int call_status = 0;
-- redirection_number.partyaddress[0] = 0;
-- redirection_number.partysubaddress[0] = 0;
-- call->callername[0] = 0;
-- call->callernum[0] = 0;
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* PTMP mode */
-+ break;
-+ }
-+ /* PTP mode */
-+ if (call->redirecting.count) {
-+ rose_diverting_leg_information2_encode(ctrl, call);
-
-+ /*
-+ * Expect a DivertingLegInformation3 to update the COLR of the
-+ * redirecting-to party we are attempting to call now.
-+ */
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ }
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ /* For Q.SIG it does network and cpe operations */
-+ if (call->redirecting.count) {
-+ rose_diverting_leg_information2_encode(ctrl, call);
-
-- /* Data checks */
-- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-- return -1;
-+ /*
-+ * Expect a DivertingLegInformation3 to update the COLR of the
-+ * redirecting-to party we are attempting to call now.
-+ */
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ }
-+ add_callername_facility_ies(ctrl, call, 1);
-+ break;
-+ case PRI_SWITCH_NI2:
-+ add_callername_facility_ies(ctrl, call, (ctrl->localtype == PRI_CPE));
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ if (ctrl->localtype == PRI_CPE) {
-+ add_dms100_transfer_ability_apdu(ctrl, call);
-+ }
-+ break;
-+ default:
-+ break;
- }
-
-- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-- } else
-- len -= 2;
-+ return 0;
-+}
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: len=%d\n", len);
-+/*!
-+ * \brief Send the CallTransferComplete/EctInform invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode call transfer.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
-+{
-+ if (rose_call_transfer_complete_encode(ctrl, call, call_status)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for call transfer completed.\n");
-+ return -1;
-+ }
-
-- do {
-- /* End Designation */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid endDesignation type 0x%X of ROSE callTransferComplete component received\n");
-- ASN1_GET_INTEGER(comp, end_designation);
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received endDesignation=%d\n", end_designation);
-+ return 0;
-+}
-
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility ETSI error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_error(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id, enum rose_error_code code)
-+{
-+ struct rose_msg_error msg;
-
-- /* Redirection Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-- if (res < 0)
-- return -1;
-- comp->len = res;
-- if (res > 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-- strncpy(call->callernum, redirection_number.partyaddress, 20);
-- call->callernum[20] = 0;
-- }
-- NEXT_COMPONENT(comp, i);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.code = code;
-
--#if 0 /* This one is optional. How do we check if it is there? */
-- /* Basic Call Info Elements */
-- GET_COMPONENT(comp, i, vdata, len);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ pos = rose_encode_error(ctrl, pos, end, &msg);
-
-+ return pos;
-+}
-
-- /* Redirection Name */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
-- if (res < 0)
-- return -1;
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility Q.SIG error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_error(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id, enum rose_error_code code)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_error msg;
-
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /* Call Status */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid callStatus type 0x%X of ROSE callTransferComplete component received\n");
-- ASN1_GET_INTEGER(comp, call_status);
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received callStatus=%d\n", call_status);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.code = code;
-
-+ pos = rose_encode_error(ctrl, pos, end, &msg);
-
-- /* Argument Extension */
--#if 0 /* Not supported */
-- GET_COMPONENT(comp, i, vdata, len);
-- switch (comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ return pos;
-+}
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
-- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+/*!
-+ * \internal
-+ * \brief Encode and queue a plain facility error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_facility_error_encode(struct pri *ctrl, q931_call *call, int invoke_id,
-+ enum rose_error_code code)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-- default:
-- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
-- return -1;
-- }
--#else
-- GET_COMPONENT(comp, i, vdata, len);
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end =
-+ enc_etsi_error(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id, code);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_error(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id, code);
-+ break;
-+ default:
-+ return -1;
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
-- if(i < len)
-- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
-+}
-
-- return 0;
-+/*!
-+ * \brief Encode and send a plain facility error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id,
-+ enum rose_error_code code)
-+{
-+ if (rose_facility_error_encode(ctrl, call, invoke_id, code)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for error message.\n");
-+ return -1;
- }
-- while (0);
-
-- return -1;
-+ return 0;
- }
-
--
--static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility ETSI result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_result_ok(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-+ struct rose_msg_result msg;
-
-- struct addressingdataelements_presentednumberscreened redirection_number;
-- redirection_number.partyaddress[0] = 0;
-- redirection_number.partysubaddress[0] = 0;
-- char redirection_name[50] = "";
-- call->callername[0] = 0;
-- call->callernum[0] = 0;
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.operation = ROSE_None;
-
-- /* Data checks */
-- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-- return -1;
-+ pos = rose_encode_result(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility Q.SIG result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_result_ok(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_result msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
- }
-
-- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-- } else
-- len -= 2;
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.operation = ROSE_None;
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: len=%d\n", len);
-+ pos = rose_encode_result(ctrl, pos, end, &msg);
-
-- do {
-- /* Redirection Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-- if (res < 0)
-- return -1;
-- comp->len = res;
-- if (res > 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-- strncpy(call->callernum, redirection_number.partyaddress, 20);
-- call->callernum[20] = 0;
-- }
-- NEXT_COMPONENT(comp, i);
-+ return pos;
-+}
-
-- /* Redirection Name */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
-- if (res < 0)
-- return -1;
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
-+/*!
-+ * \internal
-+ * \brief Encode and queue a plain ROSE result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param msgtype Q.931 message type to put facility ie in.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end =
-+ enc_etsi_result_ok(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_result_ok(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id);
-+ break;
-+ default:
-+ return -1;
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
--#if 0 /* This one is optional. How do we check if it is there? */
-- /* Basic Call Info Elements */
-- GET_COMPONENT(comp, i, vdata, len);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
-+}
-
-+/*!
-+ * \brief Encode and send a FACILITY message with a plain ROSE result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id)
-+{
-+ if (rose_result_ok_encode(ctrl, call, Q931_FACILITY, invoke_id)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for result OK message.\n");
-+ return -1;
-+ }
-
-- /* Argument Extension */
--#if 0 /* Not supported */
-- GET_COMPONENT(comp, i, vdata, len);
-- switch (comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ return 0;
-+}
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
-- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code)
-+{
-+ enum rose_error_code rose_err;
-
-- default:
-- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
-- return -1;
-- }
--#else
-- GET_COMPONENT(comp, i, vdata, len);
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-
-- if(i < len)
-- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+ /* Convert the public rerouting response code to an error code or result ok. */
-+ rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
-+ switch (code) {
-+ case PRI_REROUTING_RSP_OK_CLEAR:
-+ return rose_result_ok_encode(ctrl, call, Q931_DISCONNECT, invoke_id);
-+ case PRI_REROUTING_RSP_OK_RETAIN:
-+ return send_facility_result_ok(ctrl, call, invoke_id);
-+ case PRI_REROUTING_RSP_NOT_SUBSCRIBED:
-+ rose_err = ROSE_ERROR_Gen_NotSubscribed;
-+ break;
-+ case PRI_REROUTING_RSP_NOT_AVAILABLE:
-+ rose_err = ROSE_ERROR_Gen_NotAvailable;
-+ break;
-+ case PRI_REROUTING_RSP_NOT_ALLOWED:
-+ rose_err = ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed;
-+ break;
-+ case PRI_REROUTING_RSP_INVALID_NUMBER:
-+ rose_err = ROSE_ERROR_Div_InvalidDivertedToNr;
-+ break;
-+ case PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER:
-+ rose_err = ROSE_ERROR_Div_SpecialServiceNr;
-+ break;
-+ case PRI_REROUTING_RSP_DIVERSION_TO_SELF:
-+ rose_err = ROSE_ERROR_Div_DiversionToServedUserNr;
-+ break;
-+ case PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED:
-+ rose_err = ROSE_ERROR_Div_NumberOfDiversionsExceeded;
-+ break;
-+ case PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE:
-+ rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
-+ break;
-+ }
-+ return send_facility_error(ctrl, call, invoke_id, rose_err);
-+}
-
-- return 0;
-+/*!
-+ * \brief Handle the ROSE reject message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param reject Decoded ROSE reject message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_reject *reject)
-+{
-+ struct apdu_event *apdu;
-+ union apdu_msg_data msg;
-+
-+ /* Gripe to the user about getting rejected. */
-+ pri_error(ctrl, "ROSE REJECT:\n");
-+ if (reject->invoke_id_present) {
-+ pri_error(ctrl, "\tINVOKE ID: %d\n", reject->invoke_id);
- }
-- while (0);
-+ pri_error(ctrl, "\tPROBLEM: %s\n", rose_reject2str(reject->code));
-
-- return -1;
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
-+ return;
-+ default:
-+ break;
-+ }
-+
-+ if (!reject->invoke_id_present) {
-+ /*
-+ * No invoke id to look up so we cannot match it to any outstanding APDUs.
-+ * This REJECT is apparently meant for someone monitoring the link.
-+ */
-+ return;
-+ }
-+ apdu = pri_call_apdu_find(call, reject->invoke_id);
-+ if (!apdu) {
-+ return;
-+ }
-+ msg.reject = reject;
-+ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_REJECT, ctrl, call, apdu, &msg)) {
-+ pri_call_apdu_delete(call, apdu);
-+ }
- }
-
-+/*!
-+ * \brief Handle the ROSE error message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param error Decoded ROSE error message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_error *error)
-+{
-+ const char *dms100_operation;
-+ struct apdu_event *apdu;
-+ union apdu_msg_data msg;
-
--/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
-+ /* Gripe to the user about getting an error. */
-+ pri_error(ctrl, "ROSE RETURN ERROR:\n");
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ switch (error->invoke_id) {
-+ case ROSE_DMS100_RLT_OPERATION_IND:
-+ dms100_operation = "RLT_OPERATION_IND";
-+ break;
-+ case ROSE_DMS100_RLT_THIRD_PARTY:
-+ dms100_operation = "RLT_THIRD_PARTY";
-+ break;
-+ default:
-+ dms100_operation = NULL;
-+ break;
-+ }
-+ if (dms100_operation) {
-+ pri_error(ctrl, "\tOPERATION: %s\n", dms100_operation);
-+ break;
-+ }
-+ /* fall through */
-+ default:
-+ pri_error(ctrl, "\tINVOKE ID: %d\n", error->invoke_id);
-+ break;
-+ }
-+ pri_error(ctrl, "\tERROR: %s\n", rose_error2str(error->code));
-
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
-+ return;
-+ default:
-+ break;
-+ }
-
-+ apdu = pri_call_apdu_find(call, error->invoke_id);
-+ if (!apdu) {
-+ return;
-+ }
-+ msg.error = error;
-+ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_ERROR, ctrl, call, apdu, &msg)) {
-+ pri_call_apdu_delete(call, apdu);
-+ }
-+}
-
--int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
-+/*!
-+ * \brief Handle the ROSE result message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param result Decoded ROSE result message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_result *result)
- {
-- int i = 0;
-- int problemtag = -1;
-- int problem = -1;
-- int invokeidvalue = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
-- char *problemtagstr, *problemstr;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, invokeidvalue);
-- NEXT_COMPONENT(comp, i);
-+ struct apdu_event *apdu;
-+ union apdu_msg_data msg;
-
-- GET_COMPONENT(comp, i, vdata, len);
-- problemtag = comp->type;
-- problem = comp->data[0];
--
-- if (pri->switchtype == PRI_SWITCH_DMS100) {
-- switch (problemtag) {
-- case 0x80:
-- problemtagstr = "General problem";
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
-+ switch (result->invoke_id) {
-+ case ROSE_DMS100_RLT_OPERATION_IND:
-+ if (result->operation != ROSE_DMS100_RLT_OperationInd) {
-+ pri_message(ctrl, "Invalid Operation value in return result! %s\n",
-+ rose_operation2str(result->operation));
- break;
-- case 0x81:
-- problemtagstr = "Invoke problem";
-- break;
-- case 0x82:
-- problemtagstr = "Return result problem";
-- break;
-- case 0x83:
-- problemtagstr = "Return error problem";
-- break;
-- default:
-- problemtagstr = "Unknown";
- }
-
-- switch (problem) {
-- case 0x00:
-- problemstr = "Unrecognized component";
-- break;
-- case 0x01:
-- problemstr = "Mistyped component";
-- break;
-- case 0x02:
-- problemstr = "Badly structured component";
-- break;
-- default:
-- problemstr = "Unknown";
-+ /* We have enough data to transfer the call */
-+ call->rlt_call_id = result->args.dms100.RLT_OperationInd.call_id;
-+ call->transferable = 1;
-+ break;
-+ case ROSE_DMS100_RLT_THIRD_PARTY:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "Successfully completed RLT transfer!\n");
- }
--
-- pri_error(pri, "ROSE REJECT:\n");
-- pri_error(pri, "\tINVOKE ID: 0x%X\n", invokeidvalue);
-- pri_error(pri, "\tPROBLEM TYPE: %s (0x%x)\n", problemtagstr, problemtag);
-- pri_error(pri, "\tPROBLEM: %s (0x%x)\n", problemstr, problem);
--
-- return 0;
-- } else {
-- pri_message(pri, "Unable to handle reject on switchtype %d!\n", pri->switchtype);
-- return -1;
-+ break;
-+ default:
-+ pri_message(ctrl, "Could not parse invoke of type %d!\n", result->invoke_id);
-+ break;
- }
-+ return;
-+ default:
-+ break;
-+ }
-
-- } while(0);
--
-- return -1;
-+ apdu = pri_call_apdu_find(call, result->invoke_id);
-+ if (!apdu) {
-+ return;
-+ }
-+ msg.result = result;
-+ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_RESULT, ctrl, call, apdu, &msg)) {
-+ pri_call_apdu_delete(call, apdu);
-+ }
- }
--int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
-+
-+/*!
-+ * \brief Handle the ROSE invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param invoke Decoded ROSE invoke message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_invoke *invoke)
- {
-- int i = 0;
-- int errorvalue = -1;
-- int invokeidvalue = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
-- char *invokeidstr, *errorstr;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, invokeidvalue);
-- NEXT_COMPONENT(comp, i);
-+ struct pri_subcommand *subcmd;
-+ struct q931_party_id party_id;
-+ struct q931_party_redirecting deflection;
-
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second component in return error is 0x%x\n");
-- ASN1_GET_INTEGER(comp, errorvalue);
-+ switch (invoke->operation) {
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_ActivationDiversion:
-+ break;
-+ case ROSE_ETSI_DeactivationDiversion:
-+ break;
-+ case ROSE_ETSI_ActivationStatusNotificationDiv:
-+ break;
-+ case ROSE_ETSI_DeactivationStatusNotificationDiv:
-+ break;
-+ case ROSE_ETSI_InterrogationDiversion:
-+ break;
-+ case ROSE_ETSI_DiversionInformation:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_CallDeflection:
-+ if (!PRI_MASTER(ctrl)->deflection_support) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_NotSubscribed);
-+ break;
-+ }
-+ if (!q931_master_pass_event(ctrl, call, msgtype)) {
-+ /* Some other user is further along to connecting than this call. */
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Div_IncomingCallAccepted);
-+ break;
-+ }
-+ if (call->master_call->deflection_in_progress) {
-+ /* Someone else is already doing a call deflection. */
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Div_RequestAlreadyAccepted);
-+ break;
-+ }
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ /*
-+ * ROSE_ERROR_Gen_ResourceUnavailable was not in the list of allowed codes,
-+ * but we will send it anyway.
-+ */
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_ResourceUnavailable);
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-
-- if (pri->switchtype == PRI_SWITCH_DMS100) {
-- switch (invokeidvalue) {
-- case RLT_OPERATION_IND:
-- invokeidstr = "RLT_OPERATION_IND";
-- break;
-- case RLT_THIRD_PARTY:
-- invokeidstr = "RLT_THIRD_PARTY";
-- break;
-- default:
-- invokeidstr = "Unknown";
-- }
-+ call->master_call->deflection_in_progress = 1;
-
-- switch (errorvalue) {
-- case 0x10:
-- errorstr = "RLT Bridge Fail";
-- break;
-- case 0x11:
-- errorstr = "RLT Call ID Not Found";
-- break;
-- case 0x12:
-- errorstr = "RLT Not Allowed";
-- break;
-- case 0x13:
-- errorstr = "RLT Switch Equip Congs";
-- break;
-- default:
-- errorstr = "Unknown";
-- }
-+ q931_party_redirecting_init(&deflection);
-
-- pri_error(pri, "ROSE RETURN ERROR:\n");
-- pri_error(pri, "\tOPERATION: %s\n", invokeidstr);
-- pri_error(pri, "\tERROR: %s\n", errorstr);
-+ /* Deflecting from the called address. */
-+ q931_party_address_to_id(&deflection.from, &call->called);
-+ if (invoke->args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present) {
-+ deflection.from.number.presentation =
-+ invoke->args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user
-+ ? PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED
-+ : PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ } else {
-+ deflection.from.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-
-- return 0;
-+ /* Deflecting to the new address. */
-+ rose_copy_address_to_q931(ctrl, &deflection.to,
-+ &invoke->args.etsi.CallDeflection.deflection);
-+ deflection.to.number.presentation = deflection.from.number.presentation;
-+
-+ deflection.count = (call->redirecting.count < PRI_MAX_REDIRECTS)
-+ ? call->redirecting.count + 1 : PRI_MAX_REDIRECTS;
-+ deflection.reason = PRI_REDIR_DEFLECTION;
-+ if (deflection.count == 1) {
-+ deflection.orig_called = deflection.from;
-+ deflection.orig_reason = deflection.reason;
- } else {
-- pri_message(pri, "Unable to handle return error on switchtype %d!\n", pri->switchtype);
-+ deflection.orig_called = call->redirecting.orig_called;
-+ deflection.orig_reason = call->redirecting.orig_reason;
- }
-
-- } while(0);
--
-- return -1;
--}
-+ subcmd->cmd = PRI_SUBCMD_REROUTING;
-+ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
-+ subcmd->u.rerouting.subscription_option = 3;/* notApplicable */
-+ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &call->local_id);
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
-+ &deflection);
-+ break;
-+ case ROSE_ETSI_CallRerouting:
-+ if (!PRI_MASTER(ctrl)->deflection_support) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_NotSubscribed);
-+ break;
-+ }
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_ResourceUnavailable);
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-
--int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
--{
-- int i = 0;
-- int operationidvalue = -1;
-- int invokeidvalue = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, invokeidvalue);
-- NEXT_COMPONENT(comp, i);
-+ q931_party_redirecting_init(&deflection);
-
-- if (pri->switchtype == PRI_SWITCH_DMS100) {
-- switch (invokeidvalue) {
-- case RLT_THIRD_PARTY:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed RLT transfer!\n");
-- return 0;
-- case RLT_OPERATION_IND:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Received RLT_OPERATION_IND\n");
-- /* Have to take out the rlt_call_id */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Protocol error detected in parsing RLT_OPERATION_IND return result!\n");
-+ /* Rerouting from the last address. */
-+ rose_copy_presented_number_unscreened_to_q931(ctrl, &deflection.from.number,
-+ &invoke->args.etsi.CallRerouting.last_rerouting);
-
-- /* Traverse the contents of this sequence */
-- /* First is the Operation Value */
-- SUB_COMPONENT(comp, i);
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "RLT_OPERATION_IND should be of type ASN1_INTEGER!\n");
-- ASN1_GET_INTEGER(comp, operationidvalue);
-+ /* Rerouting to the new address. */
-+ rose_copy_address_to_q931(ctrl, &deflection.to,
-+ &invoke->args.etsi.CallRerouting.called_address);
-+ switch (invoke->args.etsi.CallRerouting.subscription_option) {
-+ default:
-+ case 0: /* noNotification */
-+ case 1: /* notificationWithoutDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case 2: /* notificationWithDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-
-- if (operationidvalue != RLT_OPERATION_IND) {
-- pri_message(pri, "Invalid Operation ID value (0x%x) in return result!\n", operationidvalue);
-- return -1;
-- }
-+ /* Calling party subaddress update. */
-+ party_id = call->local_id;
-
-- /* Next is the Call ID */
-- NEXT_COMPONENT(comp, i);
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_TAG_0, "Error check failed on Call ID!\n");
-- ASN1_GET_INTEGER(comp, call->rlt_call_id);
-- /* We have enough data to transfer the call */
-- call->transferable = 1;
-+ deflection.count = invoke->args.etsi.CallRerouting.rerouting_counter;
-+ deflection.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.etsi.CallRerouting.rerouting_reason);
-+ if (deflection.count == 1) {
-+ deflection.orig_called = deflection.from;
-+ deflection.orig_reason = deflection.reason;
-+ } else {
-+ deflection.orig_called = call->redirecting.orig_called;
-+ deflection.orig_reason = call->redirecting.orig_reason;
-+ }
-
-- return 0;
--
-- default:
-- pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
-- return -1;
-+ subcmd->cmd = PRI_SUBCMD_REROUTING;
-+ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
-+ subcmd->u.rerouting.subscription_option =
-+ invoke->args.etsi.CallRerouting.subscription_option;
-+ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &party_id);
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
-+ &deflection);
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_InterrogateServedUserNumbers:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_DivertingLegInformation1:
-+ if (invoke->args.etsi.DivertingLegInformation1.diverted_to_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl, &party_id.number,
-+ &invoke->args.etsi.DivertingLegInformation1.diverted_to);
-+ /*
-+ * We set the presentation value since the sender cannot know the
-+ * presentation value preference of the destination party.
-+ */
-+ if (party_id.number.str[0]) {
-+ party_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ } else {
-+ party_id.number.presentation =
-+ PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
- }
-- } else if (pri->switchtype == PRI_SWITCH_QSIG) {
-- switch (invokeidvalue) {
-- case 0x13:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
-- return 0;
-- }
- } else {
-- pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
-- return -1;
-+ q931_party_number_init(&party_id.number);
-+ party_id.number.valid = 1;
- }
-
-- } while(0);
--
-- return -1;
--}
-+ /*
-+ * Unless otherwise indicated by CONNECT, the divertedToNumber will be
-+ * the remote_id.number.
-+ */
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number = party_id.number;
-+ }
-
--int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
--{
-- int i = 0;
-- int res = 0;
-- int operation_tag;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
--#if 0
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
--#endif
-- invokeid = comp;
-- NEXT_COMPONENT(comp, i);
-+ /* divertedToNumber is put in redirecting.to.number */
-+ switch (invoke->args.etsi.DivertingLegInformation1.subscription_option) {
-+ default:
-+ case 0: /* noNotification */
-+ case 1: /* notificationWithoutDivertedToNr */
-+ q931_party_number_init(&call->redirecting.to.number);
-+ call->redirecting.to.number.valid = 1;
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case 2: /* notificationWithDivertedToNr */
-+ call->redirecting.to.number = party_id.number;
-+ break;
-+ }
-
-- /* Operation Tag */
-- GET_COMPONENT(comp, i, vdata, len);
--#if 0
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n");
--#endif
-- operationid = comp;
-- ASN1_GET_INTEGER(comp, operation_tag);
-- NEXT_COMPONENT(comp, i);
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.etsi.DivertingLegInformation1.diversion_reason);
-+ if (call->redirecting.count < PRI_MAX_REDIRECTS) {
-+ ++call->redirecting.count;
-+ }
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ break;
-+ case ROSE_ETSI_DivertingLegInformation2:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3;
-+ call->redirecting.count =
-+ invoke->args.etsi.DivertingLegInformation2.diversion_counter;
-+ if (!call->redirecting.count) {
-+ /* To be safe, make sure that the count is non-zero. */
-+ call->redirecting.count = 1;
-+ }
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.etsi.DivertingLegInformation2.diversion_reason);
-
-- /* No argument - return with error */
-- if (i >= len)
-- return -1;
-+ /* divertingNr is put in redirecting.from.number */
-+ if (invoke->args.etsi.DivertingLegInformation2.diverting_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.from.number,
-+ &invoke->args.etsi.DivertingLegInformation2.diverting);
-+ } else if (!call->redirecting_number_in_message) {
-+ q931_party_number_init(&call->redirecting.from.number);
-+ call->redirecting.from.number.valid = 1;
-+ }
-
-- /* Arguement Tag */
-- GET_COMPONENT(comp, i, vdata, len);
-- if (!comp->type)
-- return -1;
-+ call->redirecting.orig_reason = PRI_REDIR_UNKNOWN;
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " [ Handling operation %d ]\n", operation_tag);
-- switch (operation_tag) {
-- case SS_CNID_CALLINGNAME:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Handle Name display operation\n");
-- return rose_calling_name_decode(pri, call, comp, len-i);
-- case ROSE_CALL_TRANSFER_IDENTIFY:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_ABANDON:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_INITIATE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_SETUP:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_ACTIVE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferActive - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_COMPLETE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- {
-- pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ /* originalCalledNr is put in redirecting.orig_called.number */
-+ if (invoke->args.etsi.DivertingLegInformation2.original_called_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.orig_called.number,
-+ &invoke->args.etsi.DivertingLegInformation2.original_called);
-+ } else {
-+ q931_party_number_init(&call->redirecting.orig_called.number);
-+ }
-+ break;
-+ case ROSE_ETSI_DivertingLegInformation3:
-+ /*
-+ * Unless otherwise indicated by CONNECT, this will be the
-+ * remote_id.number.presentation.
-+ */
-+ if (!invoke->args.etsi.DivertingLegInformation3.presentation_allowed_indicator) {
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
- }
-- return rose_call_transfer_complete_decode(pri, call, comp, len-i);
-- case ROSE_CALL_TRANSFER_UPDATE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- {
-- pri_message(pri, "ROSE %i: Handle CallTransferUpdate\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+
-+ switch (call->redirecting.state) {
-+ case Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
- }
-- return rose_call_transfer_update_decode(pri, call, comp, len-i);
-- case ROSE_SUBADDRESS_TRANSFER:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_DIVERTING_LEG_INFORMATION2:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
-- case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
-- dump_apdu (pri, comp->data, comp->len);
-- }
-- return -1;
-- case ROSE_AOC_CHARGING_REQUEST:
-- return aoc_aoce_charging_request_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-- case ROSE_AOC_AOCS_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-S Currency - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCS_SPECIAL_ARR:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-S Special Array - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCD_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-D Currency - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCD_CHARGING_UNIT:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCE_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-E Currency - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCE_CHARGING_UNIT:
-- return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-- if (0) { /* the following function is currently not used - just to make the compiler happy */
-- aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */
-- return 0;
-- }
-- case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC Identification Of Charge - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case SS_ANFPR_PATHREPLACEMENT:
-- /* Clear Queue */
-- res = pri_call_apdu_queue_cleanup(call->bridged_call);
-- if (res) {
-- pri_message(pri, "Could not Clear queue ADPU\n");
-- return -1;
-- }
-- anfpr_pathreplacement_respond(pri, call, ie);
-- break;
-+ /* Setup redirecting subcommand */
-+ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
-+ &call->redirecting);
-+ break;
- default:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ break;
-+ }
-+ break;
-+ case ROSE_ETSI_ChargingRequest:
-+ /* Ignore messsage */
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_AOCSCurrency:
-+ break;
-+ case ROSE_ETSI_AOCSSpecialArr:
-+ break;
-+ case ROSE_ETSI_AOCDCurrency:
-+ break;
-+ case ROSE_ETSI_AOCDChargingUnit:
-+ break;
-+ case ROSE_ETSI_AOCECurrency:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_AOCEChargingUnit:
-+ call->aoc_units = 0;
-+ if (invoke->args.etsi.AOCEChargingUnit.type == 1
-+ && !invoke->args.etsi.AOCEChargingUnit.charging_unit.free_of_charge) {
-+ unsigned index;
-+
-+ for (index =
-+ invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
-+ num_records; index--;) {
-+ if (!invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
-+ list[index].not_available) {
-+ call->aoc_units +=
-+ invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.
-+ recorded.list[index].number_of_units;
-+ }
- }
-- return -1;
- }
-- } while(0);
--
-- return -1;
--}
-+ /* the following function is currently not used - just to make the compiler happy */
-+ if (0) {
-+ /* use this function to forward the aoc-e on a bridged channel */
-+ aoc_aoce_charging_unit_encode(ctrl, call, call->aoc_units);
-+ }
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ITU_IdentificationOfCharge:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_EctExecute:
-+ break;
-+ case ROSE_ETSI_ExplicitEctExecute:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_RequestSubaddress:
-+ /* Ignore since we are not handling subaddresses yet. */
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_SubaddressTransfer:
-+ break;
-+ case ROSE_ETSI_EctLinkIdRequest:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_EctInform:
-+ /* redirectionNumber is put in remote_id.number */
-+ if (invoke->args.etsi.EctInform.redirection_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->remote_id.number, &invoke->args.etsi.EctInform.redirection);
-+ }
-+ if (!invoke->args.etsi.EctInform.status) {
-+ /* The remote party for the transfer has not answered yet. */
-+ call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
-+ } else {
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
-+ }
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_EctLoopTest:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_CallingName:
-+ /* CallingName is put in remote_id.name */
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CallingName.name);
-+ break;
-+ case ROSE_QSIG_CalledName:
-+ /* CalledName is put in remote_id.name */
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CalledName.name);
-
--int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data)
--{
-- struct apdu_event *cur = NULL;
-- struct apdu_event *new_event = NULL;
-+ /* Setup connected line subcommand */
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-+ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
-+ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
-+ break;
-+ case ROSE_QSIG_ConnectedName:
-+ /* ConnectedName is put in remote_id.name */
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.ConnectedName.name);
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_BusyName:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_ChargeRequest:
-+ break;
-+ case ROSE_QSIG_GetFinalCharge:
-+ break;
-+ case ROSE_QSIG_AocFinal:
-+ break;
-+ case ROSE_QSIG_AocInterim:
-+ break;
-+ case ROSE_QSIG_AocRate:
-+ break;
-+ case ROSE_QSIG_AocComplete:
-+ break;
-+ case ROSE_QSIG_AocDivChargeReq:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_CallTransferIdentify:
-+ break;
-+ case ROSE_QSIG_CallTransferAbandon:
-+ break;
-+ case ROSE_QSIG_CallTransferInitiate:
-+ break;
-+ case ROSE_QSIG_CallTransferSetup:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_CallTransferActive:
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
-
-- if (!call || !messagetype || !apdu || (apdu_len < 1) || (apdu_len > 255))
-- return -1;
-+ /* connectedAddress is put in remote_id */
-+ rose_copy_presented_address_screened_to_q931(ctrl, &call->remote_id,
-+ &invoke->args.qsig.CallTransferActive.connected);
-
-- if (!(new_event = calloc(1, sizeof(*new_event)))) {
-- pri_error(call->pri, "!! Malloc failed!\n");
-- return -1;
-- }
-+ /* connectedName is put in remote_id.name */
-+ if (invoke->args.qsig.CallTransferActive.connected_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CallTransferActive.connected_name);
-+ }
-+ break;
-+ case ROSE_QSIG_CallTransferComplete:
-+ /* redirectionNumber is put in remote_id.number */
-+ rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
-+ &invoke->args.qsig.CallTransferComplete.redirection);
-
-- new_event->message = messagetype;
-- new_event->callback = function;
-- new_event->data = data;
-- memcpy(new_event->apdu, apdu, apdu_len);
-- new_event->apdu_len = apdu_len;
--
-- if (call->apdus) {
-- cur = call->apdus;
-- while (cur->next) {
-- cur = cur->next;
-+ /* redirectionName is put in remote_id.name */
-+ if (invoke->args.qsig.CallTransferComplete.redirection_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CallTransferComplete.redirection_name);
- }
-- cur->next = new_event;
-- } else
-- call->apdus = new_event;
-
-- return 0;
--}
-+ if (invoke->args.qsig.CallTransferComplete.call_status == 1) {
-+ /* The remote party for the transfer has not answered yet. */
-+ call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
-+ } else {
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
-+ }
-+ break;
-+ case ROSE_QSIG_CallTransferUpdate:
-+ party_id = call->remote_id;
-
--int pri_call_apdu_queue_cleanup(q931_call *call)
--{
-- struct apdu_event *cur_event = NULL, *free_event = NULL;
-+ /* redirectionNumber is put in party_id.number */
-+ rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
-+ &invoke->args.qsig.CallTransferUpdate.redirection);
-
-- if (call && call->apdus) {
-- cur_event = call->apdus;
-- while (cur_event) {
-- /* TODO: callbacks, some way of giving return res on status of apdu */
-- free_event = cur_event;
-- cur_event = cur_event->next;
-- free(free_event);
-+ /* redirectionName is put in party_id.name */
-+ if (invoke->args.qsig.CallTransferUpdate.redirection_name_present) {
-+ rose_copy_name_to_q931(ctrl, &party_id.name,
-+ &invoke->args.qsig.CallTransferUpdate.redirection_name);
- }
-- call->apdus = NULL;
-- }
-
-- return 0;
--}
--
--int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
--{
-- if (!pri->sendfacility)
-- return 0;
--
-- if (pri->switchtype == PRI_SWITCH_QSIG) { /* For Q.SIG it does network and cpe operations */
-- if (call->redirectingnum[0])
-- rose_diverting_leg_information2_encode(pri, call);
-- add_callername_facility_ies(pri, call, 1);
-- return 0;
-- }
--
--#if 0
-- if (pri->localtype == PRI_NETWORK) {
-- switch (pri->switchtype) {
-- case PRI_SWITCH_NI2:
-- add_callername_facility_ies(pri, call, 0);
-+ if (q931_party_id_cmp(&party_id, &call->remote_id)) {
-+ /* The remote_id data has changed. */
-+ call->remote_id = party_id;
-+ switch (call->incoming_ct_state) {
-+ case INCOMING_CT_STATE_IDLE:
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
- break;
- default:
- break;
-+ }
- }
-- return 0;
-- } else if (pri->localtype == PRI_CPE) {
-- switch (pri->switchtype) {
-- case PRI_SWITCH_NI2:
-- add_callername_facility_ies(pri, call, 1);
-- break;
-- default:
-- break;
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_SubaddressTransfer:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_PathReplacement:
-+ anfpr_pathreplacement_respond(ctrl, call, ie);
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_ActivateDiversionQ:
-+ break;
-+ case ROSE_QSIG_DeactivateDiversionQ:
-+ break;
-+ case ROSE_QSIG_InterrogateDiversionQ:
-+ break;
-+ case ROSE_QSIG_CheckRestriction:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_CallRerouting:
-+ if (!PRI_MASTER(ctrl)->deflection_support) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_NotSubscribed);
-+ break;
- }
-- return 0;
-- }
--#else
-- if (pri->switchtype == PRI_SWITCH_NI2)
-- add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
--#endif
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_ResourceUnavailable);
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-
-- if ((pri->switchtype == PRI_SWITCH_DMS100) && (pri->localtype == PRI_CPE)) {
-- add_dms100_transfer_ability_apdu(pri, call);
-- }
-+ q931_party_redirecting_init(&deflection);
-
-+ /* Rerouting from the last address. */
-+ rose_copy_presented_number_unscreened_to_q931(ctrl, &deflection.from.number,
-+ &invoke->args.qsig.CallRerouting.last_rerouting);
-+ if (invoke->args.qsig.CallRerouting.redirecting_name_present) {
-+ rose_copy_name_to_q931(ctrl, &deflection.from.name,
-+ &invoke->args.qsig.CallRerouting.redirecting_name);
-+ }
-
-+ /* Rerouting to the new address. */
-+ rose_copy_address_to_q931(ctrl, &deflection.to,
-+ &invoke->args.qsig.CallRerouting.called);
-+ switch (invoke->args.qsig.CallRerouting.subscription_option) {
-+ default:
-+ case 0: /* noNotification */
-+ case 1: /* notificationWithoutDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case 2: /* notificationWithDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-
-- return 0;
-+ /* Calling party update. */
-+ party_id = call->local_id;
-+ rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
-+ &invoke->args.qsig.CallRerouting.calling);
-+ if (invoke->args.qsig.CallRerouting.calling_name_present) {
-+ rose_copy_name_to_q931(ctrl, &party_id.name,
-+ &invoke->args.qsig.CallRerouting.calling_name);
-+ }
-+
-+ deflection.count = invoke->args.qsig.CallRerouting.diversion_counter;
-+ deflection.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.CallRerouting.rerouting_reason);
-+
-+ /* Original called party update. */
-+ if (deflection.count == 1) {
-+ deflection.orig_called = deflection.from;
-+ deflection.orig_reason = deflection.reason;
-+ } else {
-+ deflection.orig_called = call->redirecting.orig_called;
-+ deflection.orig_reason = call->redirecting.orig_reason;
-+ }
-+ if (invoke->args.qsig.CallRerouting.original_called_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &deflection.orig_called.number,
-+ &invoke->args.qsig.CallRerouting.original_called);
-+ }
-+ if (invoke->args.qsig.CallRerouting.original_called_name_present) {
-+ rose_copy_name_to_q931(ctrl, &deflection.orig_called.name,
-+ &invoke->args.qsig.CallRerouting.original_called_name);
-+ }
-+ if (invoke->args.qsig.CallRerouting.original_rerouting_reason_present) {
-+ deflection.orig_reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.CallRerouting.original_rerouting_reason);
-+ }
-+
-+ subcmd->cmd = PRI_SUBCMD_REROUTING;
-+ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
-+ subcmd->u.rerouting.subscription_option =
-+ invoke->args.qsig.CallRerouting.subscription_option;
-+ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &party_id);
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
-+ &deflection);
-+ break;
-+ case ROSE_QSIG_DivertingLegInformation1:
-+ q931_party_number_init(&party_id.number);
-+ rose_copy_number_to_q931(ctrl, &party_id.number,
-+ &invoke->args.qsig.DivertingLegInformation1.nominated_number);
-+ if (party_id.number.str[0]) {
-+ party_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-+
-+ /*
-+ * Unless otherwise indicated by CONNECT, the nominatedNr will be
-+ * the remote_id.number.
-+ */
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number = party_id.number;
-+ }
-+
-+ /* nominatedNr is put in redirecting.to.number */
-+ switch (invoke->args.qsig.DivertingLegInformation1.subscription_option) {
-+ default:
-+ case QSIG_NO_NOTIFICATION:
-+ case QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR:
-+ q931_party_number_init(&call->redirecting.to.number);
-+ call->redirecting.to.number.valid = 1;
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR:
-+ call->redirecting.to.number = party_id.number;
-+ break;
-+ }
-+
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.DivertingLegInformation1.diversion_reason);
-+ if (call->redirecting.count < PRI_MAX_REDIRECTS) {
-+ ++call->redirecting.count;
-+ }
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ break;
-+ case ROSE_QSIG_DivertingLegInformation2:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3;
-+ call->redirecting.count =
-+ invoke->args.qsig.DivertingLegInformation2.diversion_counter;
-+ if (!call->redirecting.count) {
-+ /* To be safe, make sure that the count is non-zero. */
-+ call->redirecting.count = 1;
-+ }
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.DivertingLegInformation2.diversion_reason);
-+
-+ /* divertingNr is put in redirecting.from.number */
-+ if (invoke->args.qsig.DivertingLegInformation2.diverting_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.from.number,
-+ &invoke->args.qsig.DivertingLegInformation2.diverting);
-+ } else if (!call->redirecting_number_in_message) {
-+ q931_party_number_init(&call->redirecting.from.number);
-+ call->redirecting.from.number.valid = 1;
-+ }
-+
-+ /* redirectingName is put in redirecting.from.name */
-+ if (invoke->args.qsig.DivertingLegInformation2.redirecting_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->redirecting.from.name,
-+ &invoke->args.qsig.DivertingLegInformation2.redirecting_name);
-+ } else {
-+ q931_party_name_init(&call->redirecting.from.name);
-+ }
-+
-+ call->redirecting.orig_reason = PRI_REDIR_UNKNOWN;
-+ if (invoke->args.qsig.DivertingLegInformation2.original_diversion_reason_present) {
-+ call->redirecting.orig_reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.DivertingLegInformation2.original_diversion_reason);
-+ }
-+
-+ /* originalCalledNr is put in redirecting.orig_called.number */
-+ if (invoke->args.qsig.DivertingLegInformation2.original_called_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.orig_called.number,
-+ &invoke->args.qsig.DivertingLegInformation2.original_called);
-+ } else {
-+ q931_party_number_init(&call->redirecting.orig_called.number);
-+ }
-+
-+ /* originalCalledName is put in redirecting.orig_called.name */
-+ if (invoke->args.qsig.DivertingLegInformation2.original_called_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->redirecting.orig_called.name,
-+ &invoke->args.qsig.DivertingLegInformation2.original_called_name);
-+ } else {
-+ q931_party_name_init(&call->redirecting.orig_called.name);
-+ }
-+ break;
-+ case ROSE_QSIG_DivertingLegInformation3:
-+ /*
-+ * Unless otherwise indicated by CONNECT, this will be the
-+ * remote_id.number.presentation.
-+ */
-+ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) {
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-+ }
-+
-+ /* redirectionName is put in redirecting.to.name */
-+ if (invoke->args.qsig.DivertingLegInformation3.redirection_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->redirecting.to.name,
-+ &invoke->args.qsig.DivertingLegInformation3.redirection_name);
-+ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) {
-+ call->redirecting.to.name.presentation = PRI_PRES_RESTRICTED;
-+ }
-+ } else {
-+ q931_party_name_init(&call->redirecting.to.name);
-+ }
-+
-+ switch (call->redirecting.state) {
-+ case Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-+ /* Setup redirecting subcommand */
-+ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
-+ &call->redirecting);
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_CfnrDivertedLegFailed:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_MWIActivate:
-+ break;
-+ case ROSE_QSIG_MWIDeactivate:
-+ break;
-+ case ROSE_QSIG_MWIInterrogate:
-+ break;
-+#endif /* Not handled yet */
-+ default:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "!! ROSE invoke operation not handled! %s\n",
-+ rose_operation2str(invoke->operation));
-+ }
-+ break;
-+ }
- }
--
-Index: pri_facility.h
-===================================================================
---- a/pri_facility.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_facility.h (.../branches/1.4) (revision 1357)
-@@ -31,123 +31,21 @@
- #define _PRI_FACILITY_H
- #include "pri_q931.h"
-
-+/* Forward declare some structs */
-+struct fac_extension_header;
-+struct rose_msg_invoke;
-+struct rose_msg_result;
-+struct rose_msg_error;
-+struct rose_msg_reject;
-+
- /* Protocol Profile field */
-+#define Q932_PROTOCOL_MASK 0x1F
- #define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
- #define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */
- #define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */
- #define Q932_PROTOCOL_GAT 0x16
- #define Q932_PROTOCOL_EXTENSIONS 0x1F
-
--/* 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 +67,112 @@
- #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
-+/* Q.SIG Subscription Option. Listed in ECMA-174 */
-+#define QSIG_NO_NOTIFICATION 0x00
-+#define QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR 0x01
-+#define QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR 0x02
-
--struct rose_component {
-- u_int8_t type;
-- u_int8_t len;
-- u_int8_t data[0];
-+/*! Reasons an APDU callback is called. */
-+enum APDU_CALLBACK_REASON {
-+ /*!
-+ * \brief Send setup error. Abort and cleanup.
-+ * \note The message may or may not actually get sent.
-+ * \note The callback cannot generate an event subcmd.
-+ * \note The callback should not send messages. Out of order messages will result.
-+ */
-+ APDU_CALLBACK_REASON_ERROR,
-+ /*!
-+ * \brief Abort and cleanup.
-+ * \note The APDU queue is being destroyed.
-+ * \note The callback cannot generate an event subcmd.
-+ * \note The callback cannot send messages as the call is likely being destroyed.
-+ */
-+ APDU_CALLBACK_REASON_CLEANUP,
-+ /*!
-+ * \brief Timeout waiting for responses to the message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_TIMEOUT,
-+ /*!
-+ * \brief Received a facility response message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_MSG_RESULT,
-+ /*!
-+ * \brief Received a facility error message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_MSG_ERROR,
-+ /*!
-+ * \brief Received a facility reject message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_MSG_REJECT,
- };
-
--#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
-+union apdu_msg_data {
-+ const struct rose_msg_result *result;
-+ const struct rose_msg_error *error;
-+ const struct rose_msg_reject *reject;
-+};
-
--#define NEXT_COMPONENT(component, idx) \
-- (idx) += (component)->len + 2
-+union apdu_callback_param {
-+ void *ptr;
-+ long value;
-+ char pad[8];
-+};
-
--#define SUB_COMPONENT(component, idx) \
-- (idx) += 2
-+struct apdu_callback_data {
-+ /*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
-+ int invoke_id;
-+ /*!
-+ * \brief Time to wait for responses to APDU in ms.
-+ * \note Set to 0 if send the message only.
-+ * \note Set to less than 0 for PRI_TIMER_T_RESPONSE time.
-+ */
-+ int timeout_time;
-+ /*!
-+ * \brief APDU callback function.
-+ *
-+ * \param reason Reason callback is called.
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param apdu APDU queued entry. Do not change!
-+ * \param msg APDU response message data. (NULL if was not the reason called.)
-+ *
-+ * \note
-+ * A callback must be supplied if the sender cares about any APDU_CALLBACK_REASON.
-+ *
-+ * \return TRUE if no more responses are expected.
-+ */
-+ int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg);
-+ /*! \brief Sender data for the callback function to identify the particular APDU. */
-+ union apdu_callback_param user;
-+};
-
--#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)
-+struct apdu_event {
-+ /*! Linked list pointer */
-+ struct apdu_event *next;
-+ /*! TRUE if this APDU has been sent. */
-+ int sent;
-+ /*! What message to send the ADPU in */
-+ int message;
-+ /*! Sender supplied information to handle APDU response messages. */
-+ struct apdu_callback_data response;
-+ /*! Q.931 call leg. (Needed for the APDU timeout.) */
-+ struct q931_call *call;
-+ /*! Response timeout timer. */
-+ int timer;
-+ /*! Length of ADPU */
-+ int apdu_len;
-+ /*! ADPU to send */
-+ unsigned char apdu[255];
-+};
-
--#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);
-
-@@ -310,21 +182,31 @@
- int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
-
- int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
-+int send_reroute_request(struct pri *ctrl, q931_call *call, const struct q931_party_id *caller, const struct q931_party_redirecting *deflection, int subscription_option);
-
- /* starts a QSIG Path Replacement */
- int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
-
--/* Use this function to queue a facility-IE born APDU onto a call
-- * call is the call to use, messagetype is any one of the Q931 messages,
-- * apdu is the apdu data, apdu_len is the length of the apdu data */
--int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
-+int send_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
-
--/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
--int pri_call_apdu_queue_cleanup(q931_call *call);
-+int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
-+int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);
-
-+int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
-+int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
-+
-+int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response);
-+void pri_call_apdu_queue_cleanup(q931_call *call);
-+void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed);
-+
- /* Adds the "standard" APDUs to a call */
- int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
-
--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);
-
-+void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_invoke *invoke);
-+void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_result *result);
-+void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
-+void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
-+
- #endif /* _PRI_FACILITY_H */
-Index: libpri.h
-===================================================================
---- a/libpri.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/libpri.h (.../branches/1.4) (revision 1357)
-@@ -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
-
-@@ -73,7 +80,8 @@
- #define PRI_EVENT_ANSWER 8 /* Call has been answered (CONNECT) */
- #define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
- #define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel (RESTART_ACKNOWLEDGE) */
--#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
-+#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility (DEPRECATED) */
-+#define PRI_EVENT_FACILITY 11 /* Facility received (FACILITY) */
- #define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (digits) received (INFORMATION) */
- #define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING */
- #define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
-@@ -81,6 +89,14 @@
- #define PRI_EVENT_NOTIFY 16 /* Notification received (NOTIFY) */
- #define PRI_EVENT_PROGRESS 17 /* When we get PROGRESS */
- #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state (INFORMATION) */
-+#define PRI_EVENT_SERVICE 19 /* SERVICE maintenance message */
-+#define PRI_EVENT_SERVICE_ACK 20 /* SERVICE maintenance acknowledgement message */
-+#define PRI_EVENT_HOLD 21 /* HOLD request received */
-+#define PRI_EVENT_HOLD_ACK 22 /* HOLD_ACKNOWLEDGE received */
-+#define PRI_EVENT_HOLD_REJ 23 /* HOLD_REJECT received */
-+#define PRI_EVENT_RETRIEVE 24 /* RETRIEVE request received */
-+#define PRI_EVENT_RETRIEVE_ACK 25 /* RETRIEVE_ACKNOWLEDGE received */
-+#define PRI_EVENT_RETRIEVE_REJ 26 /* RETRIEVE_REJECT received */
-
- /* Simple states */
- #define PRI_STATE_DOWN 0
-@@ -101,13 +117,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
-@@ -135,16 +151,49 @@
- #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)
-+
-+/* Reverse Charging Indication */
-+#define PRI_REVERSECHARGE_NONE -1
-+#define PRI_REVERSECHARGE_REQUESTED 1
-+
- /* Causes for disconnection */
- #define PRI_CAUSE_UNALLOCATED 1
- #define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2 /* !Q.SIG */
-@@ -157,6 +206,7 @@
- #define PRI_CAUSE_NO_ANSWER 19
- #define PRI_CAUSE_CALL_REJECTED 21
- #define PRI_CAUSE_NUMBER_CHANGED 22
-+#define PRI_CAUSE_NONSELECTED_USER_CLEARING 26
- #define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27
- #define PRI_CAUSE_INVALID_NUMBER_FORMAT 28
- #define PRI_CAUSE_FACILITY_REJECTED 29 /* !Q.SIG */
-@@ -169,6 +219,7 @@
- #define PRI_CAUSE_ACCESS_INFO_DISCARDED 43 /* !Q.SIG */
- #define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44
- #define PRI_CAUSE_PRE_EMPTED 45 /* !Q.SIG */
-+#define PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED 47
- #define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50 /* !Q.SIG */
- #define PRI_CAUSE_OUTGOING_CALL_BARRED 52 /* !Q.SIG */
- #define PRI_CAUSE_INCOMING_CALL_BARRED 54 /* !Q.SIG */
-@@ -259,8 +310,8 @@
- #define PRI_RATE_ADAPT_ASYNC 0x40
-
- /* Notifications */
--#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended */
--#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed */
-+#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended (Q.931) (Call is placed on hold) */
-+#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed (Q.931) (Call is taken off hold) */
- #define PRI_NOTIFY_BEARER_CHANGE 0x02 /* Bearer service change (DSS1) */
- #define PRI_NOTIFY_ASN1_COMPONENT 0x03 /* ASN.1 encoded component (DSS1) */
- #define PRI_NOTIFY_COMPLETION_DELAY 0x04 /* Call completion delay */
-@@ -275,12 +326,12 @@
- #define PRI_NOTIFY_CONF_OTHER_DISCONNECTED 0x4a /* Other party disconnected */
- #define PRI_NOTIFY_CONF_FLOATING 0x4b /* Conference floating */
- #define PRI_NOTIFY_WAITING_CALL 0x60 /* Call is waiting call */
--#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) */
--#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting */
--#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active */
-+#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */
-+#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting (EN 300 369-1 Section 7.2) */
-+#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active(answered) (EN 300 369-1 Section 7.2) */
- #define PRI_NOTIFY_REMOTE_HOLD 0x79 /* Remote hold */
- #define PRI_NOTIFY_REMOTE_RETRIEVAL 0x7a /* Remote retrieval */
--#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting */
-+#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting (EN 300 207-1 Section 7.2.1) */
-
- #define PRI_COPY_DIGITS_CALLED_NUMBER
-
-@@ -305,6 +356,200 @@
-
- typedef struct q931_call q931_call;
-
-+/* Name character set enumeration values */
-+#define PRI_CHAR_SET_UNKNOWN 0
-+#define PRI_CHAR_SET_ISO8859_1 1
-+#define PRI_CHAR_SET_WITHDRAWN 2
-+#define PRI_CHAR_SET_ISO8859_2 3
-+#define PRI_CHAR_SET_ISO8859_3 4
-+#define PRI_CHAR_SET_ISO8859_4 5
-+#define PRI_CHAR_SET_ISO8859_5 6
-+#define PRI_CHAR_SET_ISO8859_7 7
-+#define PRI_CHAR_SET_ISO10646_BMPSTRING 8
-+#define PRI_CHAR_SET_ISO10646_UTF_8STRING 9
-+
-+/*! \brief Q.SIG name information. */
-+struct pri_party_name {
-+ /*! \brief TRUE if the name information is valid/present */
-+ int valid;
-+ /*!
-+ * \brief Q.931 presentation-indicator encoded field
-+ * \note Must tollerate the Q.931 screening-indicator field values being present.
-+ */
-+ int presentation;
-+ /*!
-+ * \brief Character set the name is using.
-+ * \details
-+ * unknown(0),
-+ * iso8859-1(1),
-+ * enum-value-withdrawn-by-ITU-T(2)
-+ * iso8859-2(3),
-+ * iso8859-3(4),
-+ * iso8859-4(5),
-+ * iso8859-5(6),
-+ * iso8859-7(7),
-+ * iso10646-BmpString(8),
-+ * iso10646-utf-8String(9)
-+ * \details
-+ * Set to iso8859-1(1) if unsure what to use.
-+ */
-+ int char_set;
-+ /*! \brief Name data with null terminator. */
-+ char str[64];
-+};
-+
-+struct pri_party_number {
-+ /*! \brief TRUE if the number information is valid/present */
-+ int valid;
-+ /*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
-+ int presentation;
-+ /*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
-+ int plan;
-+ /*! \brief Number data with null terminator. */
-+ char str[64];
-+};
-+
-+/*!
-+ * \note This structure is a place holder for possible future subaddress support
-+ * to maintain ABI compatibility.
-+ */
-+struct pri_party_subaddress {
-+ /*! \brief TRUE if the subaddress information is valid/present */
-+ int valid;
-+ /*!
-+ * \brief Subaddress type.
-+ * \details
-+ * nsap(0),
-+ * user_specified(2)
-+ */
-+ int type;
-+ /*!
-+ * \brief TRUE if odd number of address signals
-+ * \note The odd/even indicator is used when the type of subaddress is
-+ * user_specified and the coding is BCD.
-+ */
-+ int odd_even_indicator;
-+ /*! \brief Length of the subaddress data */
-+ int length;
-+ /*!
-+ * \brief Subaddress data with null terminator.
-+ * \note The null terminator is a convenience only since the data could be
-+ * BCD/binary and thus have a null byte as part of the contents.
-+ */
-+ unsigned char data[32];
-+};
-+
-+/*! \brief Information needed to identify an endpoint in a call. */
-+struct pri_party_id {
-+ /*! \brief Subscriber name */
-+ struct pri_party_name name;
-+ /*! \brief Subscriber phone number */
-+ struct pri_party_number number;
-+ /*! \brief Subscriber subaddress */
-+ struct pri_party_subaddress subaddress;
-+};
-+
-+/*! \brief Connected Line/Party information */
-+struct pri_party_connected_line {
-+ /*! Connected party ID */
-+ struct pri_party_id id;
-+};
-+
-+/*!
-+ * \brief Redirecting Line information.
-+ * \details
-+ * RDNIS (Redirecting Directory Number Information Service)
-+ * Where a call diversion or transfer was invoked.
-+ */
-+struct pri_party_redirecting {
-+ /*! Who is redirecting the call (Sent to the party the call is redirected toward) */
-+ struct pri_party_id from;
-+ /*! Call is redirecting to a new party (Sent to the caller) */
-+ struct pri_party_id to;
-+ /*! Originally called party (in cases of multiple redirects) */
-+ struct pri_party_id orig_called;
-+ /*! Number of times the call was redirected */
-+ int count;
-+ /*! Original reason for redirect (in cases of multiple redirects) */
-+ int orig_reason;
-+ /*! Redirection reason */
-+ int reason;
-+};
-+
-+/*!
-+ * \brief Information for rerouting/deflecting the call.
-+ */
-+struct pri_rerouting_data {
-+ /*!
-+ * \brief Updated caller-id information.
-+ * \note The information may have been altered by procedure in the private network.
-+ */
-+ struct pri_party_id caller;
-+ /*!
-+ * \note
-+ * deflection.to is the new called number and must always be present.
-+ */
-+ struct pri_party_redirecting deflection;
-+ /*!
-+ * \brief Diverting user subscription option to specify if caller is notified.
-+ * \details
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2),
-+ * notApplicable(3) (Status only.)
-+ */
-+ int subscription_option;
-+ /*! Invocation ID to use when sending a reply to the call rerouting/deflection request. */
-+ int invoke_id;
-+};
-+
-+/* Subcommands derived from supplementary services. */
-+#define PRI_SUBCMD_REDIRECTING 1
-+#define PRI_SUBCMD_CONNECTED_LINE 2
-+#define PRI_SUBCMD_REROUTING 3
-+
-+
-+struct pri_subcommand {
-+ /*! PRI_SUBCMD_xxx defined values */
-+ int cmd;
-+ union {
-+ /*! Reserve room for possible expansion to maintain ABI compatibility. */
-+ char reserve_space[512];
-+ struct pri_party_connected_line connected_line;
-+ struct pri_party_redirecting redirecting;
-+ struct pri_rerouting_data rerouting;
-+ } u;
-+};
-+
-+/* Max number of subcommands per event message */
-+#define PRI_MAX_SUBCOMMANDS 8
-+
-+struct pri_subcommands {
-+ int counter_subcmd;
-+ struct pri_subcommand subcmd[PRI_MAX_SUBCOMMANDS];
-+};
-+
-+
-+/*
-+ * Event channel parameter encoding:
-+ * 3322 2222 2222 1111 1111 1100 0000 0000
-+ * 1098 7654 3210 9876 5432 1098 7654 3210
-+ * xxxx xxxx xxxx xEDC BBBBBBBBB AAAAAAAAA
-+ *
-+ * Bit field
-+ * A - B channel
-+ * B - Span (DS1) (0 - 127)
-+ * C - DS1 Explicit bit
-+ * D - D channel (cis_call) bit (status only)
-+ * E - Call is held bit (status only)
-+ *
-+ * B channel values:
-+ * 0 - No channel (ISDN uses for call waiting feature)
-+ * 1-127 - B channel #
-+ * 0xFF - Any channel (Also if whole channel value is -1 in event)
-+ */
-+
-+
- typedef struct pri_event_generic {
- /* Events with no additional information fall in this category */
- int e;
-@@ -328,6 +573,7 @@
- int progressmask;
- q931_call *call;
- char useruserinfo[260]; /* User->User info */
-+ struct pri_subcommands *subcmds;
- } pri_event_ringing;
-
- typedef struct pri_event_answer {
-@@ -338,8 +584,10 @@
- int progressmask;
- q931_call *call;
- char useruserinfo[260]; /* User->User info */
-+ struct pri_subcommands *subcmds;
- } pri_event_answer;
-
-+/*! Deprecated replaced by struct pri_event_facility. */
- typedef struct pri_event_facname {
- int e;
- char callingname[256];
-@@ -351,6 +599,24 @@
- int callingplan; /* Dialing plan of Calling entity */
- } pri_event_facname;
-
-+struct pri_event_facility {
-+ int e;
-+ char callingname[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
-+ char callingnum[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
-+ int channel;
-+ int cref;
-+ /*!
-+ * \brief Master call or normal call.
-+ * \note Call pointer known about by upper layer.
-+ * \note NULL if dummy call reference.
-+ */
-+ q931_call *call;
-+ int callingpres; /*!< Presentation of Calling CallerID (Deprecated, preserved for struct pri_event_facname compatibility) */
-+ int callingplan; /*!< Dialing plan of Calling entity (Deprecated, preserved for struct pri_event_facname compatibility) */
-+ struct pri_subcommands *subcmds;
-+ q931_call *subcall; /*!< Subcall to send any reply toward. */
-+};
-+
- #define PRI_CALLINGPLANANI
- #define PRI_CALLINGPLANRDNIS
- typedef struct pri_event_ring {
-@@ -376,13 +642,18 @@
- int layer1; /* User layer 1 */
- int complete; /* Have we seen "Complete" i.e. no more number? */
- q931_call *call; /* Opaque call pointer */
-- char callingsubaddr[256]; /* Calling parties subaddress */
-+ char callingsubaddr[256]; /* Calling parties subaddress, backwards compatibility */
- int progress;
- int progressmask;
- char origcalledname[256];
- char origcallednum[256];
- int callingplanorigcalled; /* Dialing plan of Originally Called Number */
- int origredirectingreason;
-+ int reversecharge;
-+ struct pri_subcommands *subcmds;
-+ struct pri_party_id calling; /* Calling Party's info, initially subaddress' */
-+ struct pri_party_subaddress called_subaddress; /* Called party's subaddress */
-+ char keypad_digits[64]; /* Keypad digits in the SETUP message. */
- } pri_event_ring;
-
- typedef struct pri_event_hangup {
-@@ -390,10 +661,23 @@
- int channel; /* Channel requested */
- int cause;
- int cref;
-- q931_call *call; /* Opaque call pointer */
-+ q931_call *call; /* Opaque call pointer of call hanging up. */
- long aoc_units; /* Advise of Charge number of charged units */
- char useruserinfo[260]; /* User->User info */
--} pri_event_hangup;
-+ struct pri_subcommands *subcmds;
-+ /*!
-+ * \brief Opaque held call pointer for possible transfer to active call.
-+ * \note The call_held and call_active pointers must not be NULL if
-+ * transfer held call on disconnect is available.
-+ */
-+ q931_call *call_held;
-+ /*!
-+ * \brief Opaque active call pointer for possible transfer with held call.
-+ * \note The call_held and call_active pointers must not be NULL if
-+ * transfer held call on disconnect is available.
-+ */
-+ q931_call *call_active;
-+} pri_event_hangup;
-
- typedef struct pri_event_restart_ack {
- int e;
-@@ -409,18 +693,22 @@
- int progressmask;
- int cause;
- q931_call *call;
-+ struct pri_subcommands *subcmds;
- } pri_event_proceeding;
--
-+
- typedef struct pri_event_setup_ack {
- int e;
- int channel;
- q931_call *call;
-+ struct pri_subcommands *subcmds;
- } pri_event_setup_ack;
-
- typedef struct pri_event_notify {
- int e;
- int channel;
- int info;
-+ struct pri_subcommands *subcmds;
-+ q931_call *call;
- } pri_event_notify;
-
- typedef struct pri_event_keypad_digit {
-@@ -428,14 +716,72 @@
- int channel;
- q931_call *call;
- char digits[64];
-+ struct pri_subcommands *subcmds;
- } pri_event_keypad_digit;
-
-+typedef struct pri_event_service {
-+ int e;
-+ int channel;
-+ int changestatus;
-+} pri_event_service;
-+
-+typedef struct pri_event_service_ack {
-+ int e;
-+ int channel;
-+ int changestatus;
-+} pri_event_service_ack;
-+
-+struct pri_event_hold {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_hold_ack {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_hold_rej {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ int cause;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_retrieve {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ int flexible; /* Are we flexible with our channel selection? */
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_retrieve_ack {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_retrieve_rej {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ int cause;
-+ struct pri_subcommands *subcmds;
-+};
-+
- typedef union {
- int e;
- pri_event_generic gen; /* Generic view */
- pri_event_restart restart; /* Restart view */
- pri_event_error err; /* Error view */
-- pri_event_facname facname; /* Caller*ID Name on Facility */
-+ pri_event_facname facname; /* Caller*ID Name on Facility (Deprecated, use pri_event.facility) */
- pri_event_ring ring; /* Ring */
- pri_event_hangup hangup; /* Hang up */
- pri_event_ringing ringing; /* Ringing */
-@@ -445,6 +791,15 @@
- pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
- pri_event_notify notify; /* Notification */
- pri_event_keypad_digit digit; /* Digits that come during a call */
-+ pri_event_service service; /* service message */
-+ pri_event_service_ack service_ack; /* service acknowledgement message */
-+ struct pri_event_facility facility;
-+ struct pri_event_hold hold;
-+ struct pri_event_hold_ack hold_ack;
-+ struct pri_event_hold_rej hold_rej;
-+ struct pri_event_retrieve retrieve;
-+ struct pri_event_retrieve_ack retrieve_ack;
-+ struct pri_event_retrieve_rej retrieve_rej;
- } pri_event;
-
- struct pri;
-@@ -456,7 +811,7 @@
-
- /* Create a D-channel on a given file descriptor. The file descriptor must be a
- channel operating in HDLC mode with FCS computed by the fd's driver. Also it
-- must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
-+ must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
- must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
- struct pri *pri_new(int fd, int nodetype, int switchtype);
- struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
-@@ -521,7 +876,7 @@
-
- #define PRI_KEYPAD_FACILITY_TX
- /* Send a keypad facility string of digits */
--int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits);
-+int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
-
- /* Answer the incomplete(call without called number) call on the given channel.
- Set non-isdn to non-zero if you are not connecting to ISDN equipment */
-@@ -531,6 +886,18 @@
- Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
-
-+/*!
-+ * \brief Give connected line information to a call
-+ * \note Could be used instead of pri_sr_set_caller_party() before calling pri_setup().
-+ */
-+int pri_connected_line_update(struct pri *pri, q931_call *call, const struct pri_party_connected_line *connected);
-+
-+/*!
-+ * \brief Give redirection information to a call
-+ * \note Could be used instead of pri_sr_set_redirecting_parties() before calling pri_setup().
-+ */
-+int pri_redirecting_update(struct pri *pri, q931_call *call, const struct pri_party_redirecting *redirecting);
-+
- /* Set CRV reference for GR-303 calls */
-
-
-@@ -556,9 +923,20 @@
-
- int pri_reset(struct pri *pri, int channel);
-
-+/* handle b-channel maintenance messages */
-+extern int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus);
-+
- /* Create a new call */
- q931_call *pri_new_call(struct pri *pri);
-
-+/*!
-+ * \brief Deterimine if the given call control pointer is a dummy call.
-+ *
-+ * \retval TRUE if given call is a dummy call.
-+ * \retval FALSE otherwise.
-+ */
-+int pri_is_dummy_call(q931_call *call);
-+
- /* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
- int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
-
-@@ -573,8 +951,8 @@
- extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now);
-
- int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
-- int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
-- char *called,int calledplan, int ulayer1);
-+ int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
-+ char *called, int calledplan, int ulayer1);
-
- struct pri_sr *pri_sr_new(void);
- void pri_sr_free(struct pri_sr *sr);
-@@ -582,25 +960,91 @@
- int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
- int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
- int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
-+
-+/*!
-+ * \brief Set the caller party ID information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param caller Caller party ID information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller);
-+/*! \note Use pri_sr_set_caller_party() instead to pass more precise caller information. */
- int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
-+
-+/*!
-+ * \brief Set the calling subaddress information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param subaddress information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
-+
-+/*!
-+ * \brief Set the called subaddress information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param subaddress information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
-+
-+/*!
-+ * \brief Set the redirecting information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param caller Redirecting information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting);
-+/*! \note Use pri_sr_set_redirecting_parties() instead to pass more precise redirecting information. */
- int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
-+
-+/*!
-+ * \brief Set the keypad digits in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param keypad_digits Keypad digits to send.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits);
-+
- #define PRI_USER_USER_TX
- /* Set the user user field. Warning! don't send binary data accross this field */
- void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
-+void pri_sr_set_reversecharge(struct pri_sr *sr, int requested);
-
- void pri_call_set_useruser(q931_call *sr, const char *userchars);
-
- int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
-
--/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
-+/*!
-+ * \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
-+ * \note Call will automaticlly disconnect after signalling sent.
-+ */
- int pri_sr_set_connection_call_independent(struct pri_sr *req);
-
-+/*!
-+ * \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
-+ * \note Call will stay connected until explicitly disconnected.
-+ */
-+int pri_sr_set_no_channel_call(struct pri_sr *req);
-+
- /* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, deactivates */
- int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
-
- /* Send an MWI deactivate request to a remote location */
- int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
-
-+/* Set service message support flag */
-+int pri_set_service_message_support(struct pri *pri, int supportflag);
-+
- #define PRI_2BCT
- /* Attempt to pass the channels back to the NET side if compatable and
- * suscribed. Sometimes called 2 bchannel transfer (2BCT) */
-@@ -656,48 +1100,208 @@
-
- int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason);
-
-+/*!
-+ * \brief Set the call deflection/rerouting feature enable flag.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param enable TRUE to enable call deflection/rerouting feature.
-+ *
-+ * \return Nothing
-+ */
-+void pri_reroute_enable(struct pri *ctrl, int enable);
-+
-+/*!
-+ * \brief Send the CallRerouting/CallDeflection message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option);
-+
-+enum PRI_REROUTING_RSP_CODE {
-+ /*!
-+ * Rerouting invocation accepted and the network provider option
-+ * "served user call retention on invocation of diversion"
-+ * is "clear call on invocation".
-+ */
-+ PRI_REROUTING_RSP_OK_CLEAR,
-+ /*!
-+ * Rerouting invocation accepted and the network provider option
-+ * "served user call retention on invocation of diversion"
-+ * is "retain call until alerting begins at the deflected-to user".
-+ */
-+ PRI_REROUTING_RSP_OK_RETAIN,
-+ PRI_REROUTING_RSP_NOT_SUBSCRIBED,
-+ PRI_REROUTING_RSP_NOT_AVAILABLE,
-+ /*! Supplementary service interaction not allowed. */
-+ PRI_REROUTING_RSP_NOT_ALLOWED,
-+ PRI_REROUTING_RSP_INVALID_NUMBER,
-+ /*! Deflection to prohibited number (e.g., operator, police, emergency). */
-+ PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER,
-+ /*! Deflection to served user number. */
-+ PRI_REROUTING_RSP_DIVERSION_TO_SELF,
-+ PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED,
-+ PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE,
-+};
-+
-+/*!
-+ * \brief Send the CallRerouteing/CallDeflection response message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param invoke_id Value given by the initiating request.
-+ * \param code The result to send.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code);
-+
-+/*!
-+ * \brief Set the call hold feature enable flag.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param enable TRUE to enable call hold feature.
-+ *
-+ * \return Nothing
-+ */
-+void pri_hold_enable(struct pri *ctrl, int enable);
-+
-+/*!
-+ * \brief Send the HOLD message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_hold(struct pri *ctrl, q931_call *call);
-+
-+/*!
-+ * \brief Send the HOLD ACKNOWLEDGE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_hold_ack(struct pri *ctrl, q931_call *call);
-+
-+/*!
-+ * \brief Send the HOLD REJECT message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param cause Q.931 cause code for rejecting the hold request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause);
-+
-+/*!
-+ * \brief Send the RETRIEVE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param channel Encoded channel id to use. If zero do not send channel id.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_retrieve(struct pri *ctrl, q931_call *call, int channel);
-+
-+/*!
-+ * \brief Send the RETRIEVE ACKNOWLEDGE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param channel Encoded channel id to use.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
-+
-+/*!
-+ * \brief Send the RETRIEVE REJECT message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param cause Q.931 cause code for rejecting the retrieve request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
-+
- /* Get/Set PRI Timers */
- #define PRI_GETSET_TIMERS
- int pri_set_timer(struct pri *pri, int timer, int value);
- int pri_get_timer(struct pri *pri, int timer);
--int pri_timer2idx(char *timer);
-+int pri_timer2idx(const char *timer_name);
-
--#define PRI_MAX_TIMERS 32
-+/*! New configurable timers and counters must be added to the end of the list */
-+enum PRI_TIMERS_AND_COUNTERS {
-+ PRI_TIMER_N200, /*!< Maximum numer of Q.921 retransmissions */
-+ PRI_TIMER_N201, /*!< Maximum numer of octets in an information field */
-+ PRI_TIMER_N202, /*!< Maximum numer of transmissions of the TEI identity request message */
-+ PRI_TIMER_K, /*!< Maximum number of outstanding I-frames */
-
--#define PRI_TIMER_N200 0 /* Maximum numer of q921 retransmissions */
--#define PRI_TIMER_N201 1 /* Maximum numer of octets in an information field */
--#define PRI_TIMER_N202 2 /* Maximum numer of transmissions of the TEI identity request message */
--#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
-+ PRI_TIMER_T200, /*!< Time between SABME's */
-+ PRI_TIMER_T201, /*!< Minimum time between retransmissions of the TEI Identity check messages */
-+ PRI_TIMER_T202, /*!< Minimum time between transmission of TEI Identity request messages */
-+ PRI_TIMER_T203, /*!< Maximum time without exchanging packets */
-
--#define PRI_TIMER_T200 4 /* time between SABME's */
--#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */
--#define PRI_TIMER_T202 6 /* minimum time between transmission of TEI Identity request messages */
--#define PRI_TIMER_T203 7 /* maxiumum time without exchanging packets */
-+ PRI_TIMER_T300,
-+ PRI_TIMER_T301, /*!< Maximum time to respond to an ALERT */
-+ PRI_TIMER_T302,
-+ PRI_TIMER_T303, /*!< Maximum time to wait after sending a SETUP without a response */
-+ PRI_TIMER_T304,
-+ PRI_TIMER_T305, /*!< Wait for DISCONNECT acknowledge */
-+ PRI_TIMER_T306,
-+ PRI_TIMER_T307,
-+ PRI_TIMER_T308, /*!< Wait for RELEASE acknowledge */
-+ PRI_TIMER_T309, /*!< Time active calls can tollerate data link layer being down before clearing. */
-+ PRI_TIMER_T310, /*!< Maximum time between receiving a CALL_PROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
-+ PRI_TIMER_T313, /*!< Wait for CONNECT acknowledge, CPE side only */
-+ PRI_TIMER_T314,
-+ PRI_TIMER_T316, /*!< Maximum time between transmitting a RESTART and receiving a RESTART ACK */
-+ PRI_TIMER_T317,
-+ PRI_TIMER_T318,
-+ PRI_TIMER_T319,
-+ PRI_TIMER_T320,
-+ PRI_TIMER_T321,
-+ PRI_TIMER_T322,
-
--#define PRI_TIMER_T300 8
--#define PRI_TIMER_T301 9 /* maximum time to respond to an ALERT */
--#define PRI_TIMER_T302 10
--#define PRI_TIMER_T303 11 /* maximum time to wait after sending a SETUP without a response */
--#define PRI_TIMER_T304 12
--#define PRI_TIMER_T305 13
--#define PRI_TIMER_T306 14
--#define PRI_TIMER_T307 15
--#define PRI_TIMER_T308 16
--#define PRI_TIMER_T309 17
--#define PRI_TIMER_T310 18 /* maximum time between receiving a CALLPROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
--#define PRI_TIMER_T313 19
--#define PRI_TIMER_T314 20
--#define PRI_TIMER_T316 21 /* maximum time between transmitting a RESTART and receiving a RESTART ACK */
--#define PRI_TIMER_T317 22
--#define PRI_TIMER_T318 23
--#define PRI_TIMER_T319 24
--#define PRI_TIMER_T320 25
--#define PRI_TIMER_T321 26
--#define PRI_TIMER_T322 27
-+ PRI_TIMER_TM20, /*!< Maximum time awaiting XID response */
-+ PRI_TIMER_NM20, /*!< Number of XID retransmits */
-
--#define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
--#define PRI_TIMER_NM20 29 /* number of XID retransmits */
-+ PRI_TIMER_T_HOLD, /*!< Maximum time to wait for HOLD request response. */
-+ PRI_TIMER_T_RETRIEVE, /*!< Maximum time to wait for RETRIEVE request response. */
-
-+ PRI_TIMER_T_RESPONSE, /*!< Maximum time to wait for a typical APDU response. */
-+
-+ /* Must be last in the enum list */
-+ PRI_MAX_TIMERS
-+};
-+
- /* Get PRI version */
- const char *pri_get_version(void);
-
-Index: asn1_primitive.c
-===================================================================
---- a/asn1_primitive.c (.../tags/1.4.10.2) (revision 0)
-+++ b/asn1_primitive.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,1306 @@
-+/*
-+ * 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 BER encode/decode primitives
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include <stdio.h>
-+#include <ctype.h>
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "asn1.h"
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Dump the memory contents indicated in printable characters. (Helper function.)
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param start Dump memory starting position.
-+ * \param end Dump memory ending position. (Not included in dump.)
-+ *
-+ * \return Nothing
-+ */
-+static void asn1_dump_mem_helper(struct pri *ctrl, const unsigned char *start,
-+ const unsigned char *end)
-+{
-+ pri_message(ctrl, " - \"");
-+ for (; start < end; ++start) {
-+ pri_message(ctrl, "%c", (isprint(*start)) ? *start : '~');
-+ }
-+ pri_message(ctrl, "\"\n");
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Dump the memory contents indicated.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param indent Number of spaces to indent for each new memory dump line.
-+ * \param pos Dump memory starting position.
-+ * \param length Number of bytes to dump.
-+ *
-+ * \return Nothing
-+ */
-+static void asn1_dump_mem(struct pri *ctrl, unsigned indent, const unsigned char *pos,
-+ unsigned length)
-+{
-+ const unsigned char *seg_start;
-+ const unsigned char *end;
-+ unsigned delimiter;
-+ unsigned count;
-+
-+ seg_start = pos;
-+ end = pos + length;
-+ if (pos < end) {
-+ delimiter = '<';
-+ for (;;) {
-+ pri_message(ctrl, "%*s", indent, "");
-+ for (count = 0; count++ < 16 && pos < end;) {
-+ pri_message(ctrl, "%c%02X", delimiter, *pos++);
-+ delimiter = (count == 8) ? '-' : ' ';
-+ }
-+ if (end <= pos) {
-+ break;
-+ }
-+ asn1_dump_mem_helper(ctrl, seg_start, pos);
-+ seg_start = pos;
-+ }
-+ } else {
-+ pri_message(ctrl, "%*s<", indent, "");
-+ }
-+ pri_message(ctrl, ">");
-+ asn1_dump_mem_helper(ctrl, seg_start, end);
-+}
-+
-+/*!
-+ * \brief Convert the given tag value to a descriptive string.
-+ *
-+ * \param tag Component tag value to convert to a string.
-+ *
-+ * \return Converted tag string.
-+ */
-+const char *asn1_tag2str(unsigned tag)
-+{
-+ static const char *primitives[32] = {
-+ [ASN1_TYPE_INDEF_TERM] = "Indefinite length terminator",
-+ [ASN1_TYPE_BOOLEAN] = "Boolean",
-+ [ASN1_TYPE_INTEGER] = "Integer",
-+ [ASN1_TYPE_BIT_STRING] = "Bit String",
-+ [ASN1_TYPE_OCTET_STRING] = "Octet String",
-+ [ASN1_TYPE_NULL] = "NULL",
-+ [ASN1_TYPE_OBJECT_IDENTIFIER] = "OID",
-+ [ASN1_TYPE_OBJECT_DESCRIPTOR] = "Object Descriptor",
-+ [ASN1_TYPE_EXTERN] = "External",
-+ [ASN1_TYPE_REAL] = "Real",
-+ [ASN1_TYPE_ENUMERATED] = "Enumerated",
-+ [ASN1_TYPE_EMBEDDED_PDV] = "Embedded PDV",
-+ [ASN1_TYPE_UTF8_STRING] = "UTF8 String",
-+ [ASN1_TYPE_RELATIVE_OID] = "Relative OID",
-+ [ASN1_TYPE_SEQUENCE] = "Sequence",
-+ [ASN1_TYPE_SET] = "Set",
-+ [ASN1_TYPE_NUMERIC_STRING] = "Numeric String",
-+ [ASN1_TYPE_PRINTABLE_STRING] = "Printable String",
-+ [ASN1_TYPE_TELETEX_STRING] = "Teletex String",
-+ [ASN1_TYPE_VIDEOTEX_STRING] = "Videotex String",
-+ [ASN1_TYPE_IA5_STRING] = "IA5 String",
-+ [ASN1_TYPE_UTC_TIME] = "UTC Time",
-+ [ASN1_TYPE_GENERALIZED_TIME] = "Generalized Time",
-+ [ASN1_TYPE_GRAPHIC_STRING] = "Graphic String",
-+ [ASN1_TYPE_VISIBLE_STRING] = "Visible/ISO646 String",
-+ [ASN1_TYPE_GENERAL_STRING] = "General String",
-+ [ASN1_TYPE_UNIVERSAL_STRING] = "Universal String",
-+ [ASN1_TYPE_CHAR_STRING] = "Character String",
-+ [ASN1_TYPE_BMP_STRING] = "BMP String",
-+ [ASN1_TYPE_EXTENSION] = "Type Extension",
-+ };
-+ static char buf[64];
-+ const char *description;
-+ unsigned asn1_constructed; /*! TRUE if the tag is constructed. */
-+ unsigned asn1_type;
-+
-+ asn1_constructed = ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED);
-+ asn1_type = tag & ASN1_TYPE_MASK;
-+
-+ switch (tag & ASN1_CLASS_MASK) {
-+ case ASN1_CLASS_UNIVERSAL:
-+ if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_INDEF_TERM)) {
-+ description = NULL;
-+ } else {
-+ description = primitives[asn1_type];
-+ }
-+ if (!description) {
-+ description = "Reserved";
-+ }
-+ snprintf(buf, sizeof(buf), "%s%s(%u 0x%02X)", description,
-+ asn1_constructed ? "/C" : "", tag, tag);
-+ return buf;
-+ case ASN1_CLASS_APPLICATION:
-+ description = "Application";
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC:
-+ description = "Context Specific";
-+ break;
-+ case ASN1_CLASS_PRIVATE:
-+ description = "Private";
-+ break;
-+ default:
-+ snprintf(buf, sizeof(buf), "Unknown tag (%u 0x%02X)", tag, tag);
-+ return buf;
-+ }
-+ snprintf(buf, sizeof(buf), "%s%s [%u 0x%02X]", description,
-+ asn1_constructed ? "/C" : "", asn1_type, asn1_type);
-+ return buf;
-+}
-+
-+/*!
-+ * \brief Decode the ASN.1 tag value.
-+ *
-+ * \param tag_pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 encoded data buffer.
-+ * \param tag Decoded tag value returned on success.
-+ *
-+ * \retval Next octet after the tag on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end,
-+ unsigned *tag)
-+{
-+ unsigned extended_tag;
-+
-+ if (end <= tag_pos) {
-+ return NULL;
-+ }
-+ *tag = *tag_pos++;
-+ if ((*tag & ASN1_TYPE_MASK) == ASN1_TYPE_EXTENSION) {
-+ /* Extract the extended tag value */
-+ extended_tag = 0;
-+ do {
-+ if (end <= tag_pos) {
-+ return NULL;
-+ }
-+ extended_tag <<= 7;
-+ extended_tag |= *tag_pos & ~0x80;
-+ } while (*tag_pos++ & 0x80);
-+ if (extended_tag && extended_tag < ASN1_TYPE_EXTENSION) {
-+ /*
-+ * The sender did not need to use the extended format.
-+ * This is an encoding error on their part, but we will
-+ * accept it anyway.
-+ *
-+ * Note we cannot return a null tag value from this path.
-+ * We would misinterpret the indefinite length
-+ * terminator.
-+ */
-+ *tag &= ~ASN1_TYPE_MASK;
-+ *tag |= extended_tag;
-+ }
-+ }
-+
-+ return tag_pos;
-+}
-+
-+/*!
-+ * \brief Decode the length of an ASN.1 component length.
-+ *
-+ * \param len_pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param length Decoded length value returned on success. (-1 if indefinite)
-+ *
-+ * \retval Next octet after the length on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The decoded length is checked to see if there is enough buffer
-+ * left for the component body.
-+ */
-+const unsigned char *asn1_dec_length(const unsigned char *len_pos,
-+ const unsigned char *end, int *length)
-+{
-+ unsigned length_size;
-+
-+ if (end <= len_pos) {
-+ /* Not enough buffer to determine how the length is encoded */
-+ return NULL;
-+ }
-+
-+ if (*len_pos < 0x80) {
-+ /* Short length encoding */
-+ *length = *len_pos++;
-+ } else if (*len_pos == 0x80) {
-+ /* Indefinite length encoding */
-+ *length = -1;
-+ ++len_pos;
-+ if (end < len_pos + ASN1_INDEF_TERM_LEN) {
-+ /* Not enough buffer for the indefinite length terminator */
-+ return NULL;
-+ }
-+ return len_pos;
-+ } else {
-+ /* Long length encoding */
-+ length_size = *len_pos++ & 0x7f;
-+ if (length_size == 0x7f) {
-+ /* Reserved extension encoding that has not been defined. */
-+ return NULL;
-+ }
-+ if (end < len_pos + length_size) {
-+ /* Not enough buffer for the length value */
-+ return NULL;
-+ }
-+ *length = 0;
-+ while (length_size--) {
-+ *length = (*length << 8) | *len_pos++;
-+ }
-+ }
-+
-+ if (end < len_pos + *length) {
-+ /* Not enough buffer for the component body. */
-+ return NULL;
-+ }
-+ return len_pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Skip to the end of an indefinite length constructed component helper.
-+ *
-+ * \param pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 decoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *asn1_dec_indef_end_fixup_helper(const unsigned char *pos,
-+ const unsigned char *end)
-+{
-+ unsigned tag;
-+ int length;
-+
-+ while (pos < end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /* Skip over indefinite length sub-component */
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED
-+ || tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
-+ || tag ==
-+ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
-+ /* This is an ITU encoded indefinite length component. */
-+ ASN1_CALL(pos, asn1_dec_indef_end_fixup_helper(pos, end));
-+ } else {
-+ /* This is a non-ITU encoded indefinite length component. */
-+ while (pos < end && *pos != ASN1_INDEF_TERM) {
-+ ++pos;
-+ }
-+ pos += ASN1_INDEF_TERM_LEN;
-+ }
-+ } else {
-+ /* Skip over defininte length sub-component */
-+ pos += length;
-+ }
-+ }
-+ if (end < pos + ASN1_INDEF_TERM_LEN) {
-+ return NULL;
-+ }
-+
-+ return pos + ASN1_INDEF_TERM_LEN;
-+}
-+
-+/*!
-+ * \brief Skip to the end of an indefinite length constructed component.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 decoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end)
-+{
-+ if (pos < end && *pos != ASN1_INDEF_TERM && (ctrl->debug & PRI_DEBUG_APDU)) {
-+ pri_message(ctrl,
-+ " Skipping unused indefinite length constructed component octets!\n");
-+ }
-+ return asn1_dec_indef_end_fixup_helper(pos, end);
-+}
-+
-+/*!
-+ * \brief Decode the boolean primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param value Decoded boolean value.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+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)
-+{
-+ int length;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length != 1) {
-+ /*
-+ * The encoding rules say the length can only be one.
-+ * It is rediculus to get anything else anyway.
-+ */
-+ return NULL;
-+ }
-+
-+ *value = *pos++ ? 1 : 0;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = %d\n", name, asn1_tag2str(tag), *value);
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the integer type primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param value Decoded integer type value.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+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)
-+{
-+ int length;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length <= 0) {
-+ /*
-+ * The encoding rules say the length can not be indefinite.
-+ * It cannot be empty for that matter either.
-+ */
-+ return NULL;
-+ }
-+
-+#if 1
-+ /* Read value as signed */
-+ if (*pos & 0x80) {
-+ /* The value is negative */
-+ *value = -1;
-+ } else {
-+ *value = 0;
-+ }
-+#else
-+ /* Read value as unsigned */
-+ *value = 0;
-+#endif
-+ while (length--) {
-+ *value = (*value << 8) | *pos;
-+ pos++;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = %d 0x%04X\n", name, asn1_tag2str(tag), *value,
-+ *value);
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the null primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end)
-+{
-+ int length;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length != 0) {
-+ /*
-+ * The encoding rules say the length can only be zero.
-+ * It is rediculus to get anything else anyway.
-+ */
-+ return NULL;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the object identifier primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param oid Decoded OID type value.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+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)
-+{
-+ int length;
-+ unsigned num_values;
-+ unsigned value;
-+ unsigned delimiter;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /*
-+ * The encoding rules say the length can not be indefinite.
-+ */
-+ return NULL;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s =", name, asn1_tag2str(tag));
-+ }
-+ delimiter = ' ';
-+ num_values = 0;
-+ while (length) {
-+ value = 0;
-+ for (;;) {
-+ --length;
-+ value = (value << 7) | (*pos & 0x7F);
-+ if (!(*pos++ & 0x80)) {
-+ /* Last octet in the OID subidentifier value */
-+ if (num_values < ARRAY_LEN(oid->value)) {
-+ oid->value[num_values] = value;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "%c%u", delimiter, value);
-+ }
-+ delimiter = '.';
-+ } else {
-+ /* Too many OID subidentifier values */
-+ delimiter = '~';
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "%c%u", delimiter, value);
-+ }
-+ }
-+ ++num_values;
-+ break;
-+ }
-+ if (!length) {
-+ oid->num_values = 0;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "\n"
-+ " Last OID subidentifier value not terminated!\n");
-+ }
-+ return NULL;
-+ }
-+ }
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "\n");
-+ }
-+
-+ if (num_values <= ARRAY_LEN(oid->value)) {
-+ oid->num_values = num_values;
-+ return pos;
-+ } else {
-+ /* Need to increase the size of the OID subidentifier list. */
-+ oid->num_values = 0;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Too many OID values!\n");
-+ }
-+ return NULL;
-+ }
-+}
-+
-+/*!
-+ * \brief Decode a binary string primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param buf_size Size of the supplied string buffer. (Must be nonzero)
-+ * \param str Where to put the decoded string.
-+ * \param str_len Length of the decoded string.
-+ *
-+ * \note The string will be null terminated just in case.
-+ * The buffer needs to have enough room for a null terminator.
-+ * \note The parse will fail if the parsed string is too large for
-+ * the supplied buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+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)
-+{
-+ int length;
-+ size_t sub_buf_size;
-+ size_t sub_str_len;
-+ unsigned char *sub_str;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /* This is an indefinite length string */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = Indefinite length string\n", name,
-+ asn1_tag2str(tag));
-+ }
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /*
-+ * This is an ITU encoded indefinite length string
-+ * and could contain null.
-+ */
-+
-+ /* Ensure that an empty string is null terminated. */
-+ *str = 0;
-+
-+ /* Collect all substrings into the original string buffer. */
-+ *str_len = 0;
-+ sub_str = str;
-+ sub_buf_size = buf_size;
-+ for (;;) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ if (tag == ASN1_INDEF_TERM) {
-+ /* End-of-contents octets */
-+ break;
-+ }
-+
-+ /* Append the substring to the accumulated indefinite string. */
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
-+ sub_buf_size, sub_str, &sub_str_len));
-+
-+ sub_buf_size -= sub_str_len;
-+ sub_str += sub_str_len;
-+ *str_len += sub_str_len;
-+ }
-+ } else {
-+ /*
-+ * This is a non-ITU encoded indefinite length string
-+ * and must not contain null's.
-+ */
-+ for (length = 0;; ++length) {
-+ if (end <= pos + length) {
-+ /* Not enough buffer left */
-+ return NULL;
-+ }
-+ if (pos[length] == 0) {
-+ /* Found End-of-contents octets */
-+ break;
-+ }
-+ }
-+
-+ if (buf_size - 1 < length) {
-+ /* The destination buffer is not large enough for the data */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " String buffer not large enough!\n");
-+ }
-+ return NULL;
-+ }
-+
-+ /* Extract the string and null terminate it. */
-+ memcpy(str, pos, length);
-+ str[length] = 0;
-+ *str_len = length;
-+
-+ pos += length + 1;
-+ }
-+ if (end <= pos) {
-+ /* Not enough buffer left for End-of-contents octets */
-+ return NULL;
-+ }
-+ if (*pos++ != 0) {
-+ /* We actually did not find the End-of-contents octets. */
-+ return NULL;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ /* Dump the collected string buffer contents. */
-+ pri_message(ctrl, " Completed string =\n");
-+ asn1_dump_mem(ctrl, 6, str, *str_len);
-+ }
-+ } else {
-+ /* This is a definite length string */
-+ if (buf_size - 1 < length) {
-+ /* The destination buffer is not large enough for the data */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = Buffer not large enough!\n", name,
-+ asn1_tag2str(tag));
-+ }
-+ return NULL;
-+ }
-+
-+ /* Extract the string and null terminate it. */
-+ memcpy(str, pos, length);
-+ str[length] = 0;
-+ *str_len = length;
-+
-+ pos += length;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ /* Dump the collected string buffer contents. */
-+ pri_message(ctrl, " %s %s =\n", name, asn1_tag2str(tag));
-+ asn1_dump_mem(ctrl, 4, str, *str_len);
-+ }
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode a string that can be truncated to a maximum length primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param buf_size Size of the supplied string buffer. (Must be nonzero)
-+ * \param str Where to put the decoded null terminated string.
-+ * \param str_len Length of the decoded string.
-+ * (computed for convenience since you could just do a strlen())
-+ *
-+ * \note The parsed string will be truncated if the string buffer
-+ * cannot contain it.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+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)
-+{
-+ int length;
-+ size_t str_length;
-+ size_t sub_buf_size;
-+ size_t sub_str_len;
-+ unsigned char *sub_str;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /* This is an indefinite length string */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = Indefinite length string\n", name,
-+ asn1_tag2str(tag));
-+ }
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /* This is an ITU encoded indefinite length string. */
-+
-+ /* Ensure that an empty string is null terminated. */
-+ *str = 0;
-+
-+ /* Collect all substrings into the original string buffer. */
-+ *str_len = 0;
-+ sub_str = str;
-+ sub_buf_size = buf_size;
-+ for (;;) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ if (tag == ASN1_INDEF_TERM) {
-+ /* End-of-contents octets */
-+ break;
-+ }
-+
-+ /* Append the substring to the accumulated indefinite string. */
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, name, tag, pos, end,
-+ sub_buf_size, sub_str, &sub_str_len));
-+
-+ sub_buf_size -= sub_str_len;
-+ sub_str += sub_str_len;
-+ *str_len += sub_str_len;
-+ }
-+ } else {
-+ /* This is a non-ITU encoded indefinite length string. */
-+ for (length = 0;; ++length) {
-+ if (end <= pos + length) {
-+ /* Not enough buffer left */
-+ return NULL;
-+ }
-+ if (pos[length] == 0) {
-+ /* Found End-of-contents octets */
-+ break;
-+ }
-+ }
-+
-+ /* Extract the string, truncate if necessary, and terminate it. */
-+ str_length = (buf_size - 1 < length) ? buf_size - 1 : length;
-+ memcpy(str, pos, str_length);
-+ str[str_length] = 0;
-+ *str_len = str_length;
-+
-+ pos += length + 1;
-+ }
-+ if (end <= pos) {
-+ /* Not enough buffer left for End-of-contents octets */
-+ return NULL;
-+ }
-+ if (*pos++ != 0) {
-+ /* We actually did not find the End-of-contents octets. */
-+ return NULL;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Completed string = \"%s\"\n", str);
-+ }
-+ } else {
-+ /*
-+ * This is a definite length string
-+ *
-+ * Extract the string, truncate if necessary, and terminate it.
-+ */
-+ str_length = (buf_size - 1 < length) ? buf_size - 1 : length;
-+ memcpy(str, pos, str_length);
-+ str[str_length] = 0;
-+ *str_len = str_length;
-+
-+ pos += length;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = \"%s\"\n", name, asn1_tag2str(tag), str);
-+ }
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Recursive ASN.1 buffer decoding dump helper.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param level Indentation level to use.
-+ * \param indefinite_term TRUE if to stop on an indefinite length terminator.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *asn1_dump_helper(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, unsigned level, unsigned indefinite_term)
-+{
-+ unsigned delimiter;
-+ unsigned tag;
-+ int length;
-+ const unsigned char *len_pos;
-+
-+ while (pos < end && (!indefinite_term || *pos != ASN1_INDEF_TERM)) {
-+ /* Decode the tag */
-+ pri_message(ctrl, "%*s", 2 * level, "");
-+ len_pos = asn1_dec_tag(pos, end, &tag);
-+ if (!len_pos) {
-+ pri_message(ctrl, "Invalid tag encoding!\n");
-+ return NULL;
-+ }
-+
-+ /* Dump the tag contents. */
-+ pri_message(ctrl, "%s ", asn1_tag2str(tag));
-+ delimiter = '<';
-+ while (pos < len_pos) {
-+ pri_message(ctrl, "%c%02X", delimiter, *pos);
-+ delimiter = ' ';
-+ ++pos;
-+ }
-+ pri_message(ctrl, "> ");
-+
-+ /* Decode the length */
-+ pos = asn1_dec_length(len_pos, end, &length);
-+ if (!pos) {
-+ pri_message(ctrl, "Invalid length encoding!\n");
-+ return NULL;
-+ }
-+
-+ /* Dump the length contents. */
-+ if (length < 0) {
-+ pri_message(ctrl, "Indefinite length ");
-+ } else {
-+ pri_message(ctrl, "Len:%d ", length);
-+ }
-+ delimiter = '<';
-+ while (len_pos < pos) {
-+ pri_message(ctrl, "%c%02X", delimiter, *len_pos);
-+ delimiter = ' ';
-+ ++len_pos;
-+ }
-+ pri_message(ctrl, ">\n");
-+
-+ /* Dump the body contents */
-+ ++level;
-+ if (length < 0) {
-+ /* Indefinite length */
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /* This is an ITU encoded indefinite length component. */
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, end, level, 1));
-+ } else if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
-+ || tag ==
-+ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
-+ pri_message(ctrl, "%*sThis tag must always be constructed!\n", 2 * level,
-+ "");
-+ /* Assume tag was constructed to keep going */
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, end, level, 1));
-+ } else {
-+ /* This is a non-ITU encoded indefinite length component. */
-+ pri_message(ctrl, "%*sNon-ITU indefininte length component.\n",
-+ 2 * level, "");
-+ length = 0;
-+ while (pos + length < end && pos[length] != ASN1_INDEF_TERM) {
-+ ++length;
-+ }
-+ if (length) {
-+ asn1_dump_mem(ctrl, 2 * level, pos, length);
-+ pos += length;
-+ }
-+ }
-+ --level;
-+ if (end < pos + ASN1_INDEF_TERM_LEN) {
-+ pri_message(ctrl, "%*sNot enough room for the End-of-contents octets!\n",
-+ 2 * level, "");
-+ pos = end;
-+ } else {
-+ pri_message(ctrl, "%*sEnd-of-contents <%02X %02X>%s\n", 2 * level, "",
-+ pos[0], pos[1], (pos[1] != 0) ? " Invalid!" : "");
-+ pos += ASN1_INDEF_TERM_LEN;
-+ }
-+ } else {
-+ /* Defininte length */
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /* Dump constructed contents */
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, pos + length, level, 0));
-+ } else if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
-+ || tag ==
-+ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
-+ /* Assume tag was constructed to keep going */
-+ pri_message(ctrl, "%*sThis tag must always be constructed!\n", 2 * level,
-+ "");
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, pos + length, level, 0));
-+ } else if (0 < length) {
-+ /* Dump primitive contents. */
-+ asn1_dump_mem(ctrl, 2 * level, pos, length);
-+ pos += length;
-+ }
-+ --level;
-+ }
-+
-+#if 0
-+ pri_message(ctrl, "%*sEnd\n", 2 * level, "");
-+#endif
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Dump the given ASN.1 buffer contents.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param start_asn1 First octet in the ASN.1 buffer. (ASN.1 tag starting position)
-+ * \param end One beyond the last octet in the ASN.1 buffer.
-+ *
-+ * \return Nothing
-+ */
-+void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1,
-+ const unsigned char *end)
-+{
-+ pri_message(ctrl, "ASN.1 dump\n");
-+ if (start_asn1) {
-+ asn1_dump_helper(ctrl, start_asn1, end, 1, 0);
-+ }
-+ pri_message(ctrl, "ASN.1 end\n");
-+}
-+
-+/*!
-+ * \brief Encode the length of an ASN.1 component body of predetermined size.
-+ *
-+ * \param len_pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param length Predetermined component body length.
-+ *
-+ * \note The encoding buffer does not need to be checked after calling.
-+ * It is already checked to have the requested room.
-+ *
-+ * \retval Next octet after the length on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end, size_t length)
-+{
-+ u_int32_t body_length; /* Length of component contents */
-+ u_int32_t value;
-+ u_int32_t test_mask;
-+ unsigned length_size; /* Length of the length encoding */
-+
-+ body_length = length;
-+
-+ /* Determine length encoding length */
-+ if (body_length < 128) {
-+ length_size = 1;
-+ } else {
-+ /* Find most significant octet of 32 bit integer that carries meaning. */
-+ test_mask = 0xFF000000;
-+ for (length_size = 4; --length_size;) {
-+ if (body_length & test_mask) {
-+ /*
-+ * Found the first 8 bits of a multiple octet length that
-+ * is not all zeroes.
-+ */
-+ break;
-+ }
-+ test_mask >>= 8;
-+ }
-+ length_size += 1 + 1;
-+ }
-+
-+ if (end < len_pos + length_size + body_length) {
-+ /* No room for the length and component body in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode the component body length */
-+ if (length_size == 1) {
-+ *len_pos++ = body_length;
-+ } else {
-+ *len_pos++ = 0x80 | --length_size;
-+ while (length_size--) {
-+ value = body_length;
-+ value >>= (8 * length_size);
-+ *len_pos++ = value & 0xFF;
-+ }
-+ }
-+
-+ return len_pos;
-+}
-+
-+/*!
-+ * \brief Encode the length of an already encoded ASN.1 component.
-+ *
-+ * \param len_pos Starting position of the ASN.1 component length.
-+ * \param component_end Next octet after the component body.
-+ * \param end End of ASN.1 encoding data buffer.
-+ *
-+ * \note The total component size could increase or decrease.
-+ * \note The component length field must have been initialized with
-+ * ASN1_LEN_INIT() or ASN1_CONSTRUCTED_BEGIN().
-+ *
-+ * \retval Next octet after the component body on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_length_fixup(unsigned char *len_pos,
-+ unsigned char *component_end, unsigned char *end)
-+{
-+ u_int32_t body_length; /* Length of component contents */
-+ u_int32_t value;
-+ u_int32_t test_mask;
-+ unsigned length_size; /* Length of the length encoding */
-+
-+ if (component_end < len_pos + *len_pos) {
-+ /* Sanity check */
-+ return NULL;
-+ }
-+
-+ body_length = component_end - len_pos - *len_pos;
-+
-+ /* Determine length encoding length */
-+ if (body_length < 128) {
-+ length_size = 1;
-+ } else {
-+ /* Find most significant octet of 32 bit integer that carries meaning. */
-+ test_mask = 0xFF000000;
-+ for (length_size = 4; --length_size;) {
-+ if (body_length & test_mask) {
-+ /*
-+ * Found the first 8 bits of a multiple octet length that
-+ * is not all zeroes.
-+ */
-+ break;
-+ }
-+ test_mask >>= 8;
-+ }
-+ length_size += 1 + 1;
-+ }
-+
-+ component_end = len_pos + length_size + body_length;
-+ if (end < component_end) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+ if (length_size != *len_pos) {
-+ /* Must shift the component body */
-+ memmove(len_pos + length_size, len_pos + *len_pos, body_length);
-+ }
-+
-+ /* Encode the component body length */
-+ if (length_size == 1) {
-+ *len_pos = body_length;
-+ } else {
-+ *len_pos++ = 0x80 | --length_size;
-+ while (length_size--) {
-+ value = body_length;
-+ value >>= (8 * length_size);
-+ *len_pos++ = value & 0xFF;
-+ }
-+ }
-+
-+ return component_end;
-+}
-+
-+/*!
-+ * \brief Encode the boolean primitive.
-+ *
-+ * \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.
-+ * \param value Component value to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag,
-+ int32_t value)
-+{
-+ if (end < pos + 3) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ *pos++ = 1;
-+ *pos++ = value ? 1 : 0;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the integer type primitive.
-+ *
-+ * \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.
-+ * \param value Component value to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag,
-+ int32_t value)
-+{
-+ unsigned count;
-+ u_int32_t test_mask;
-+ u_int32_t val;
-+
-+ /* Find most significant octet of 32 bit integer that carries meaning. */
-+ test_mask = 0xFF800000;
-+ val = (u_int32_t) value;
-+ for (count = 4; --count;) {
-+ if ((val & test_mask) != test_mask && (val & test_mask) != 0) {
-+ /*
-+ * The first 9 bits of a multiple octet integer is not
-+ * all ones or zeroes.
-+ */
-+ break;
-+ }
-+ test_mask >>= 8;
-+ }
-+
-+ if (end < pos + 3 + count) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ *pos++ = count + 1;
-+ do {
-+ val = (u_int32_t) value;
-+ val >>= (8 * count);
-+ *pos++ = val & 0xFF;
-+ } while (count--);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the null type primitive.
-+ *
-+ * \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.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag)
-+{
-+ if (end < pos + 2) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ *pos++ = 0;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the object identifier (OID) primitive.
-+ *
-+ * \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.
-+ * \param oid Component value to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct asn1_oid *oid)
-+{
-+ unsigned char *len_pos;
-+ unsigned num_values;
-+ unsigned count;
-+ u_int32_t value;
-+
-+ if (end < pos + 2) {
-+ /* No room for the component tag and length in the buffer */
-+ return NULL;
-+ }
-+
-+ *pos++ = tag;
-+ len_pos = pos++;
-+
-+ /* For all OID subidentifer values */
-+ for (num_values = 0; num_values < oid->num_values; ++num_values) {
-+ /*
-+ * Count the number of 7 bit chunks that are needed
-+ * to encode the integer.
-+ */
-+ value = oid->value[num_values] >> 7;
-+ for (count = 0; value; ++count) {
-+ /* There are bits still set */
-+ value >>= 7;
-+ }
-+
-+ if (end < pos + count + 1) {
-+ /* No room for the component body in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Store OID subidentifier value */
-+ do {
-+ value = oid->value[num_values];
-+ value >>= (7 * count);
-+ *pos++ = (value & 0x7F) | (count ? 0x80 : 0);
-+ } while (count--);
-+ }
-+
-+ /* length */
-+ *len_pos = pos - len_pos - 1;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the binary string type primitive.
-+ *
-+ * \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.
-+ * \param str Binary string to encode.
-+ * \param str_len Length of binary string to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const unsigned char *str, size_t str_len)
-+{
-+ if (end < pos + 1) {
-+ /* No room for the component tag in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ ASN1_CALL(pos, asn1_enc_length(pos, end, str_len));
-+ memcpy(pos, str, str_len);
-+
-+ return pos + str_len;
-+}
-+
-+/*!
-+ * \brief Encode a string that can be truncated to a maximum length primitive.
-+ *
-+ * \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.
-+ * \param str Null terminated string to encode.
-+ * \param max_len Maximum length of string to encode.
-+ *
-+ * \note The string will be truncated if it is too long.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const unsigned char *str, size_t max_len)
-+{
-+ size_t str_len;
-+
-+ str_len = strlen((char *) str);
-+ if (max_len < str_len) {
-+ str_len = max_len;
-+ }
-+ return asn1_enc_string_bin(pos, end, tag, str, str_len);
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end asn1_primitive.c */
-
-Property changes on: asn1_primitive.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: pri.c
-===================================================================
---- a/pri.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri.c (.../branches/1.4) (revision 1357)
-@@ -42,8 +42,56 @@
- #include "pri_facility.h"
- #include "pri_q921.h"
- #include "pri_q931.h"
--#include "pri_timers.h"
-
-+#define PRI_BIT(a_bit) (1UL << (a_bit))
-+#define PRI_ALL_SWITCHES 0xFFFFFFFF
-+
-+struct pri_timer_table {
-+ const char *name;
-+ enum PRI_TIMERS_AND_COUNTERS number;
-+ unsigned long used_by;
-+};
-+
-+/*!
-+ * \note Sort the timer table entries in the order of the timer name so
-+ * pri_dump_info_str() can display them in a consitent order.
-+ */
-+static const struct pri_timer_table pri_timer[] = {
-+/* *INDENT-OFF* */
-+ /* timer name timer number used by switches */
-+ { "N200", PRI_TIMER_N200, PRI_ALL_SWITCHES },
-+ { "N201", PRI_TIMER_N201, PRI_ALL_SWITCHES },
-+ { "N202", PRI_TIMER_N202, PRI_ALL_SWITCHES },
-+ { "K", PRI_TIMER_K, PRI_ALL_SWITCHES },
-+ { "T200", PRI_TIMER_T200, PRI_ALL_SWITCHES },
-+ { "T202", PRI_TIMER_T202, PRI_ALL_SWITCHES },
-+ { "T203", PRI_TIMER_T203, PRI_ALL_SWITCHES },
-+ { "T300", PRI_TIMER_T300, PRI_ALL_SWITCHES },
-+ { "T301", PRI_TIMER_T301, PRI_ALL_SWITCHES },
-+ { "T302", PRI_TIMER_T302, PRI_ALL_SWITCHES },
-+ { "T303", PRI_TIMER_T303, PRI_ALL_SWITCHES },
-+ { "T304", PRI_TIMER_T304, PRI_ALL_SWITCHES },
-+ { "T305", PRI_TIMER_T305, PRI_ALL_SWITCHES },
-+ { "T306", PRI_TIMER_T306, PRI_ALL_SWITCHES },
-+ { "T307", PRI_TIMER_T307, PRI_ALL_SWITCHES },
-+ { "T308", PRI_TIMER_T308, PRI_ALL_SWITCHES },
-+ { "T309", PRI_TIMER_T309, PRI_ALL_SWITCHES },
-+ { "T310", PRI_TIMER_T310, PRI_ALL_SWITCHES },
-+ { "T313", PRI_TIMER_T313, PRI_ALL_SWITCHES },
-+ { "T314", PRI_TIMER_T314, PRI_ALL_SWITCHES },
-+ { "T316", PRI_TIMER_T316, PRI_ALL_SWITCHES },
-+ { "T317", PRI_TIMER_T317, PRI_ALL_SWITCHES },
-+ { "T318", PRI_TIMER_T318, PRI_ALL_SWITCHES },
-+ { "T319", PRI_TIMER_T319, PRI_ALL_SWITCHES },
-+ { "T320", PRI_TIMER_T320, PRI_ALL_SWITCHES },
-+ { "T321", PRI_TIMER_T321, PRI_ALL_SWITCHES },
-+ { "T322", PRI_TIMER_T322, PRI_ALL_SWITCHES },
-+ { "T-HOLD", PRI_TIMER_T_HOLD, PRI_ALL_SWITCHES },
-+ { "T-RETRIEVE", PRI_TIMER_T_RETRIEVE, PRI_ALL_SWITCHES },
-+ { "T-RESPONSE", PRI_TIMER_T_RESPONSE, PRI_ALL_SWITCHES },
-+/* *INDENT-ON* */
-+};
-+
- char *pri_node2str(int node)
- {
- switch(node) {
-@@ -84,14 +132,39 @@
- }
- }
-
--static void pri_default_timers(struct pri *pri, int switchtype)
-+static void pri_default_timers(struct pri *ctrl, int switchtype)
- {
-- static const int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
-- int x;
-+ unsigned idx;
-
-- for (x = 0; x<PRI_MAX_TIMERS; x++) {
-- pri->timers[x] = defaulttimers[switchtype][x];
-+ /* Initialize all timers/counters to unsupported/disabled. */
-+ for (idx = 0; idx < PRI_MAX_TIMERS; ++idx) {
-+ ctrl->timers[idx] = -1;
- }
-+
-+ /* Set timer values to standard defaults. Time is in ms. */
-+ ctrl->timers[PRI_TIMER_N200] = 3; /* Max numer of Q.921 retransmissions */
-+ ctrl->timers[PRI_TIMER_N202] = 3; /* Max numer of transmissions of the TEI identity request message */
-+ ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
-+ ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */
-+ ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */
-+ ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */
-+ ctrl->timers[PRI_TIMER_T305] = 30 * 1000; /* Wait for DISCONNECT acknowledge */
-+ ctrl->timers[PRI_TIMER_T308] = 4 * 1000; /* Wait for RELEASE acknowledge */
-+ ctrl->timers[PRI_TIMER_T313] = 4 * 1000; /* Wait for CONNECT acknowledge, CPE side only */
-+ ctrl->timers[PRI_TIMER_TM20] = 2500; /* Max time awaiting XID response - Q.921 Appendix IV */
-+ ctrl->timers[PRI_TIMER_NM20] = 3; /* Number of XID retransmits - Q.921 Appendix IV */
-+ ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */
-+
-+ ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000; /* Wait for HOLD request response. */
-+ ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */
-+
-+ ctrl->timers[PRI_TIMER_T_RESPONSE] = 4 * 1000; /* Maximum time to wait for a typical APDU response. */
-+
-+ /* Set any switch specific override default values */
-+ switch (switchtype) {
-+ default:
-+ break;
-+ }
- }
-
- int pri_set_timer(struct pri *pri, int timer, int value)
-@@ -110,66 +183,30 @@
- return pri->timers[timer];
- }
-
--int pri_timer2idx(char *timer)
-+int pri_set_service_message_support(struct pri *pri, int supportflag)
- {
-- if (!strcasecmp(timer, "N200"))
-- return PRI_TIMER_N200;
-- else if (!strcasecmp(timer, "N201"))
-- return PRI_TIMER_N201;
-- else if (!strcasecmp(timer, "N202"))
-- return PRI_TIMER_N202;
-- else if (!strcasecmp(timer, "K"))
-- return PRI_TIMER_K;
-- else if (!strcasecmp(timer, "T200"))
-- return PRI_TIMER_T200;
-- else if (!strcasecmp(timer, "T202"))
-- return PRI_TIMER_T202;
-- else if (!strcasecmp(timer, "T203"))
-- return PRI_TIMER_T203;
-- else if (!strcasecmp(timer, "T300"))
-- return PRI_TIMER_T300;
-- else if (!strcasecmp(timer, "T301"))
-- return PRI_TIMER_T301;
-- else if (!strcasecmp(timer, "T302"))
-- return PRI_TIMER_T302;
-- else if (!strcasecmp(timer, "T303"))
-- return PRI_TIMER_T303;
-- else if (!strcasecmp(timer, "T304"))
-- return PRI_TIMER_T304;
-- else if (!strcasecmp(timer, "T305"))
-- return PRI_TIMER_T305;
-- else if (!strcasecmp(timer, "T306"))
-- return PRI_TIMER_T306;
-- else if (!strcasecmp(timer, "T307"))
-- return PRI_TIMER_T307;
-- else if (!strcasecmp(timer, "T308"))
-- return PRI_TIMER_T308;
-- else if (!strcasecmp(timer, "T309"))
-- return PRI_TIMER_T309;
-- else if (!strcasecmp(timer, "T310"))
-- return PRI_TIMER_T310;
-- else if (!strcasecmp(timer, "T313"))
-- return PRI_TIMER_T313;
-- else if (!strcasecmp(timer, "T314"))
-- return PRI_TIMER_T314;
-- else if (!strcasecmp(timer, "T316"))
-- return PRI_TIMER_T316;
-- else if (!strcasecmp(timer, "T317"))
-- return PRI_TIMER_T317;
-- else if (!strcasecmp(timer, "T318"))
-- return PRI_TIMER_T318;
-- else if (!strcasecmp(timer, "T319"))
-- return PRI_TIMER_T319;
-- else if (!strcasecmp(timer, "T320"))
-- return PRI_TIMER_T320;
-- else if (!strcasecmp(timer, "T321"))
-- return PRI_TIMER_T321;
-- else if (!strcasecmp(timer, "T322"))
-- return PRI_TIMER_T322;
-- else
-+ if (!pri) {
- return -1;
-+ }
-+ pri->service_message_support = supportflag;
-+ return 0;
- }
-
-+int pri_timer2idx(const char *timer_name)
-+{
-+ unsigned idx;
-+ enum PRI_TIMERS_AND_COUNTERS timer_number;
-+
-+ timer_number = -1;
-+ for (idx = 0; idx < ARRAY_LEN(pri_timer); ++idx) {
-+ if (!strcasecmp(timer_name, pri_timer[idx].name)) {
-+ timer_number = pri_timer[idx].number;
-+ break;
-+ }
-+ }
-+ return timer_number;
-+}
-+
- static int __pri_read(struct pri *pri, void *buf, int buflen)
- {
- int res = read(pri->fd, buf, buflen);
-@@ -192,18 +229,53 @@
- return res;
- }
-
--/* Pass in the master for this function */
- void __pri_free_tei(struct pri * p)
- {
-- free (p);
-+ if (p) {
-+ struct q931_call *call;
-+
-+ call = p->dummy_call;
-+ if (call) {
-+ pri_schedule_del(call->pri, call->retranstimer);
-+ pri_call_apdu_queue_cleanup(call);
-+ }
-+ free(p->msg_line);
-+ free(p);
-+ }
- }
-
- struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
- {
-+ struct d_ctrl_dummy *dummy_ctrl;
- struct pri *p;
-
-- if (!(p = calloc(1, sizeof(*p))))
-- return NULL;
-+ switch (switchtype) {
-+ case PRI_SWITCH_GR303_EOC:
-+ case PRI_SWITCH_GR303_TMC:
-+ case PRI_SWITCH_GR303_TMC_SWITCHING:
-+ case PRI_SWITCH_GR303_EOC_PATH:
-+ p = calloc(1, sizeof(*p));
-+ if (!p) {
-+ return NULL;
-+ }
-+ dummy_ctrl = NULL;
-+ break;
-+ default:
-+ dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
-+ if (!dummy_ctrl) {
-+ return NULL;
-+ }
-+ p = &dummy_ctrl->ctrl;
-+ break;
-+ }
-+ if (!master) {
-+ /* This is the master record. */
-+ p->msg_line = calloc(1, sizeof(*p->msg_line));
-+ if (!p->msg_line) {
-+ free(p);
-+ return NULL;
-+ }
-+ }
-
- p->bri = bri;
- p->fd = fd;
-@@ -231,7 +303,14 @@
- p->q931_rxcount = 0;
- p->q931_txcount = 0;
- #endif
-- if (switchtype == PRI_SWITCH_GR303_EOC) {
-+ if (dummy_ctrl) {
-+ /* Initialize the dummy call reference call record. */
-+ dummy_ctrl->ctrl.dummy_call = &dummy_ctrl->dummy_call;
-+ q931_init_call_record(&dummy_ctrl->ctrl, dummy_ctrl->ctrl.dummy_call,
-+ Q931_DUMMY_CALL_REFERENCE);
-+ }
-+ switch (switchtype) {
-+ case PRI_SWITCH_GR303_EOC:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_EOC;
- p->tei = Q921_TEI_GR303_EOC_OPS;
-@@ -240,7 +319,8 @@
- free(p);
- p = NULL;
- }
-- } else if (switchtype == PRI_SWITCH_GR303_TMC) {
-+ break;
-+ case PRI_SWITCH_GR303_TMC:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
- p->tei = Q921_TEI_GR303_TMC_CALLPROC;
-@@ -249,14 +329,19 @@
- free(p);
- p = NULL;
- }
-- } else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
-+ break;
-+ case PRI_SWITCH_GR303_TMC_SWITCHING:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
- p->tei = Q921_TEI_GR303_TMC_SWITCHING;
-- } else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
-+ break;
-+ case PRI_SWITCH_GR303_EOC_PATH:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_EOC;
- p->tei = Q921_TEI_GR303_EOC_PATH;
-+ break;
-+ default:
-+ break;
- }
- /* Start Q.921 layer, Wait if we're the network */
- if (p)
-@@ -327,44 +412,47 @@
-
- char *pri_event2str(int id)
- {
-- switch(id) {
-- case PRI_EVENT_DCHAN_UP:
-- return "D-Channel Up";
-- case PRI_EVENT_DCHAN_DOWN:
-- return "D-channel Down";
-- case PRI_EVENT_RESTART:
-- return "Restart channel";
-- case PRI_EVENT_RING:
-- return "Ring";
-- case PRI_EVENT_HANGUP:
-- return "Hangup";
-- case PRI_EVENT_RINGING:
-- return "Ringing";
-- case PRI_EVENT_ANSWER:
-- return "Answer";
-- case PRI_EVENT_HANGUP_ACK:
-- return "Hangup ACK";
-- case PRI_EVENT_RESTART_ACK:
-- return "Restart ACK";
-- case PRI_EVENT_FACNAME:
-- return "FacName";
-- case PRI_EVENT_INFO_RECEIVED:
-- return "Info Received";
-- case PRI_EVENT_PROCEEDING:
-- return "Proceeding";
-- case PRI_EVENT_SETUP_ACK:
-- return "Setup ACK";
-- case PRI_EVENT_HANGUP_REQ:
-- return "Hangup Req";
-- case PRI_EVENT_NOTIFY:
-- return "Notify";
-- case PRI_EVENT_PROGRESS:
-- return "Progress";
-- case PRI_EVENT_CONFIG_ERR:
-- return "Configuration Error";
-- default:
-- return "Unknown Event";
-+ unsigned idx;
-+ struct {
-+ int id;
-+ char *name;
-+ } events[] = {
-+/* *INDENT-OFF* */
-+ { PRI_EVENT_DCHAN_UP, "D-Channel Up" },
-+ { PRI_EVENT_DCHAN_DOWN, "D-channel Down" },
-+ { PRI_EVENT_RESTART, "Restart channel" },
-+ { PRI_EVENT_CONFIG_ERR, "Configuration Error" },
-+ { PRI_EVENT_RING, "Ring" },
-+ { PRI_EVENT_HANGUP, "Hangup" },
-+ { PRI_EVENT_RINGING, "Ringing" },
-+ { PRI_EVENT_ANSWER, "Answer" },
-+ { PRI_EVENT_HANGUP_ACK, "Hangup ACK" },
-+ { PRI_EVENT_RESTART_ACK, "Restart ACK" },
-+ { PRI_EVENT_FACILITY, "Facility" },
-+ { PRI_EVENT_INFO_RECEIVED, "Info Received" },
-+ { PRI_EVENT_PROCEEDING, "Proceeding" },
-+ { PRI_EVENT_SETUP_ACK, "Setup ACK" },
-+ { PRI_EVENT_HANGUP_REQ, "Hangup Req" },
-+ { PRI_EVENT_NOTIFY, "Notify" },
-+ { PRI_EVENT_PROGRESS, "Progress" },
-+ { PRI_EVENT_KEYPAD_DIGIT, "Keypad Digit" },
-+ { PRI_EVENT_SERVICE, "Service" },
-+ { PRI_EVENT_SERVICE_ACK, "Service ACK" },
-+ { PRI_EVENT_HOLD, "Hold" },
-+ { PRI_EVENT_HOLD_ACK, "Hold Ack" },
-+ { PRI_EVENT_HOLD_REJ, "Hold Rej" },
-+ { PRI_EVENT_RETRIEVE, "Retrieve" },
-+ { PRI_EVENT_RETRIEVE_ACK, "Retrieve ACK" },
-+ { PRI_EVENT_RETRIEVE_REJ, "Retrieve Rej" },
-+/* *INDENT-ON* */
-+ };
-+
-+ for (idx = 0; idx < ARRAY_LEN(events); ++idx) {
-+ if (events[idx].id == id) {
-+ return events[idx].name;
-+ }
- }
-+ return "Unknown Event";
- }
-
- pri_event *pri_check_event(struct pri *pri)
-@@ -506,7 +594,7 @@
- return q931_information(pri, call, digit);
- }
-
--int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits)
-+int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits)
- {
- if (!pri || !call || !digits || !digits[0])
- return -1;
-@@ -514,15 +602,6 @@
- return q931_keypad_facility(pri, call, digits);
- }
-
--
--int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
--{
-- if (!pri || !call)
-- return -1;
--
-- return qsig_cf_callrerouting(pri, call, dest, original, reason);
--}
--
- int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
- {
- if (!pri || !call)
-@@ -533,7 +612,7 @@
- void pri_destroycall(struct pri *pri, q931_call *call)
- {
- if (pri && call)
-- __q931_destroycall(pri, call);
-+ q931_destroycall(pri, call);
- return;
- }
-
-@@ -551,6 +630,268 @@
- return q931_connect(pri, call, channel, nonisdn);
- }
-
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party name to the Q.931 party name structure.
-+ *
-+ * \param q931_name Q.931 party name structure
-+ * \param pri_name PRI party name structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_name_to_q931(struct q931_party_name *q931_name, const struct pri_party_name *pri_name)
-+{
-+ q931_party_name_init(q931_name);
-+ if (pri_name->valid) {
-+ q931_name->valid = 1;
-+ q931_name->presentation = pri_name->presentation;
-+ q931_name->char_set = pri_name->char_set;
-+ libpri_copy_string(q931_name->str, pri_name->str, sizeof(q931_name->str));
-+ }
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party number to the Q.931 party number structure.
-+ *
-+ * \param q931_number Q.931 party number structure
-+ * \param pri_number PRI party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_number_to_q931(struct q931_party_number *q931_number, const struct pri_party_number *pri_number)
-+{
-+ q931_party_number_init(q931_number);
-+ if (pri_number->valid) {
-+ q931_number->valid = 1;
-+ q931_number->presentation = pri_number->presentation;
-+ q931_number->plan = pri_number->plan;
-+ libpri_copy_string(q931_number->str, pri_number->str, sizeof(q931_number->str));
-+ }
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party subaddress to the Q.931 party subaddress structure.
-+ *
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ * \param pri_subaddress PRI party subaddress structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_subaddress_to_q931(struct q931_party_subaddress *q931_subaddress, const struct pri_party_subaddress *pri_subaddress)
-+{
-+ int length;
-+ int maxlen = sizeof(q931_subaddress->data) - 1;
-+
-+ q931_party_subaddress_init(q931_subaddress);
-+
-+ if (!pri_subaddress->valid) {
-+ return;
-+ }
-+
-+ q931_subaddress->valid = 1;
-+ q931_subaddress->type = pri_subaddress->type;
-+
-+ length = pri_subaddress->length;
-+ if (length > maxlen){
-+ length = maxlen;
-+ } else {
-+ q931_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
-+ }
-+ q931_subaddress->length = length;
-+ memcpy(q931_subaddress->data, pri_subaddress->data, length);
-+ q931_subaddress->data[length] = '\0';
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party id to the Q.931 party id structure.
-+ *
-+ * \param q931_id Q.931 party id structure
-+ * \param pri_id PRI party id structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_party_id *pri_id)
-+{
-+ pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name);
-+ pri_copy_party_number_to_q931(&q931_id->number, &pri_id->number);
-+ pri_copy_party_subaddress_to_q931(&q931_id->subaddress, &pri_id->subaddress);
-+}
-+
-+int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected)
-+{
-+ struct q931_party_id party_id;
-+ unsigned idx;
-+ struct q931_call *subcall;
-+
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+
-+ pri_copy_party_id_to_q931(&party_id, &connected->id);
-+ q931_party_id_fixup(ctrl, &party_id);
-+ if (!q931_party_id_cmp(&party_id, &call->local_id)) {
-+ /* The local party information did not change so do nothing. */
-+ return 0;
-+ }
-+ call->local_id = party_id;
-+
-+ /* Update all subcalls with new local_id. */
-+ if (call->outboundbroadcast && call->master_call == call) {
-+ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
-+ subcall = call->subcalls[idx];
-+ if (subcall) {
-+ subcall->local_id = party_id;
-+ }
-+ }
-+ }
-+
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_INITIATED:
-+ case Q931_CALL_STATE_OVERLAP_SENDING:
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ /*
-+ * The local party transferred to someone else before
-+ * the remote end answered.
-+ */
-+ case Q931_CALL_STATE_ACTIVE:
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* PTMP mode */
-+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
-+ &call->local_id.number);
-+ } else {
-+ /* PTP mode */
-+ /* Immediately send EctInform APDU, callStatus=answered(0) */
-+ send_call_transfer_complete(ctrl, call, 0);
-+ }
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
-+ send_call_transfer_complete(ctrl, call, 0);
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+ default:
-+ /* Just save the data for further developments. */
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_party_redirecting *redirecting)
-+{
-+ unsigned idx;
-+ struct q931_call *subcall;
-+
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+
-+ /* Save redirecting.to information and reason. */
-+ pri_copy_party_id_to_q931(&call->redirecting.to, &redirecting->to);
-+ q931_party_id_fixup(ctrl, &call->redirecting.to);
-+ call->redirecting.reason = redirecting->reason;
-+
-+ /*
-+ * Update all subcalls with new redirecting.to information and reason.
-+ * I do not think we will ever have any subcalls when this data is relevant,
-+ * but update it just in case.
-+ */
-+ if (call->outboundbroadcast && call->master_call == call) {
-+ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
-+ subcall = call->subcalls[idx];
-+ if (subcall) {
-+ subcall->redirecting.to = call->redirecting.to;
-+ subcall->redirecting.reason = redirecting->reason;
-+ }
-+ }
-+ }
-+
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_NULL:
-+ /* Save the remaining redirecting information before we place a call. */
-+ pri_copy_party_id_to_q931(&call->redirecting.from, &redirecting->from);
-+ q931_party_id_fixup(ctrl, &call->redirecting.from);
-+ pri_copy_party_id_to_q931(&call->redirecting.orig_called, &redirecting->orig_called);
-+ q931_party_id_fixup(ctrl, &call->redirecting.orig_called);
-+ call->redirecting.orig_reason = redirecting->orig_reason;
-+ if (redirecting->count <= 0) {
-+ if (call->redirecting.from.number.valid) {
-+ /*
-+ * We are redirecting with an unknown count
-+ * so assume the count is one.
-+ */
-+ call->redirecting.count = 1;
-+ } else {
-+ call->redirecting.count = 0;
-+ }
-+ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
-+ call->redirecting.count = redirecting->count;
-+ } else {
-+ call->redirecting.count = PRI_MAX_REDIRECTS;
-+ }
-+ break;
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ /* This is an incoming call that has not connected yet. */
-+ if (!call->redirecting.to.number.valid) {
-+ /* Not being redirected toward valid number data. Ignore. */
-+ break;
-+ }
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* PTMP mode */
-+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
-+ &call->redirecting.to.number);
-+ break;
-+ }
-+ /* PTP mode - same behaviour as Q.SIG */
-+ /* fall through */
-+ case PRI_SWITCH_QSIG:
-+ if (call->redirecting.state != Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3
-+ || strcmp(call->redirecting.to.number.str, call->called.number.str) != 0) {
-+ /* immediately send divertingLegInformation1 APDU */
-+ if (rose_diverting_leg_information1_encode(ctrl, call)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for divertingLegInfo1\n");
-+ }
-+ }
-+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+
-+ /* immediately send divertingLegInformation3 APDU */
-+ if (rose_diverting_leg_information3_encode(ctrl, call, Q931_FACILITY)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for divertingLegInfo3\n");
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+ default:
-+ pri_message(ctrl, "Ignored redirecting update because call in state %s(%d).\n",
-+ q931_call_state_str(call->ourcallstate), call->ourcallstate);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
- #if 0
- /* deprecated routines, use pri_hangup */
- int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -619,7 +960,7 @@
- return -1;
- if (cause == -1)
- /* normal clear cause */
-- cause = 16;
-+ cause = PRI_CAUSE_NORMAL_CLEARING;
- return q931_hangup(pri, call, cause);
- }
-
-@@ -630,6 +971,14 @@
- return q931_restart(pri, channel);
- }
-
-+int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus)
-+{
-+ if (!pri) {
-+ return -1;
-+ }
-+ return maintenance_service(pri, span, channel, changestatus);
-+}
-+
- q931_call *pri_new_call(struct pri *pri)
- {
- if (!pri)
-@@ -637,6 +986,14 @@
- return q931_new_call(pri);
- }
-
-+int pri_is_dummy_call(q931_call *call)
-+{
-+ if (!call) {
-+ return 0;
-+ }
-+ return q931_is_dummy_call(call);
-+}
-+
- void pri_dump_event(struct pri *pri, pri_event *e)
- {
- if (!pri || !e)
-@@ -667,7 +1024,10 @@
- static void pri_sr_init(struct pri_sr *req)
- {
- memset(req, 0, sizeof(struct pri_sr));
--
-+ q931_party_redirecting_init(&req->redirecting);
-+ q931_party_id_init(&req->caller);
-+ q931_party_address_init(&req->called);
-+ req->reversecharge = PRI_REVERSECHARGE_NONE;
- }
-
- int pri_sr_set_connection_call_independent(struct pri_sr *req)
-@@ -675,10 +1035,21 @@
- if (!req)
- return -1;
-
-- req->justsignalling = 1; /* have to set justsignalling for all those pesky IEs we need to setup */
-+ req->cis_call = 1; /* have to set cis_call for all those pesky IEs we need to setup */
-+ req->cis_auto_disconnect = 1;
- return 0;
- }
-
-+int pri_sr_set_no_channel_call(struct pri_sr *req)
-+{
-+ if (!req) {
-+ return -1;
-+ }
-+
-+ req->cis_call = 1;
-+ return 0;
-+}
-+
- /* Don't call any other pri functions on this */
- int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
- int calledplan)
-@@ -689,14 +1060,9 @@
-
- pri_sr_init(&req);
- pri_sr_set_connection_call_independent(&req);
-+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
-+ pri_sr_set_called(&req, called, calledplan, 0);
-
-- req.caller = caller;
-- req.callerplan = callerplan;
-- req.callername = callername;
-- req.callerpres = callerpres;
-- req.called = called;
-- req.calledplan = calledplan;
--
- if (mwi_message_send(pri, c, &req, 1) < 0) {
- pri_message(pri, "Unable to send MWI activate message\n");
- return -1;
-@@ -714,14 +1080,9 @@
-
- pri_sr_init(&req);
- pri_sr_set_connection_call_independent(&req);
-+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
-+ pri_sr_set_called(&req, called, calledplan, 0);
-
-- req.caller = caller;
-- req.callerplan = callerplan;
-- req.callername = callername;
-- req.callerpres = callerpres;
-- req.called = called;
-- req.calledplan = calledplan;
--
- if(mwi_message_send(pri, c, &req, 0) < 0) {
- pri_message(pri, "Unable to send MWI deactivate message\n");
- return -1;
-@@ -740,22 +1101,18 @@
-
- int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
- int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
-- int calledplan,int ulayer1)
-+ int calledplan, int ulayer1)
- {
- struct pri_sr req;
- if (!pri || !c)
- return -1;
- pri_sr_init(&req);
-+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
-+ pri_sr_set_called(&req, called, calledplan, 0);
- req.transmode = transmode;
- req.channel = channel;
- req.exclusive = exclusive;
- req.nonisdn = nonisdn;
-- req.caller = caller;
-- req.callerplan = callerplan;
-- req.callername = callername;
-- req.callerpres = callerpres;
-- req.called = called;
-- req.calledplan = calledplan;
- req.userl1 = ulayer1;
- return q931_setup(pri, c, &req);
- }
-@@ -773,28 +1130,85 @@
- __pri_error = func;
- }
-
--void pri_message(struct pri *pri, char *fmt, ...)
-+static void pri_old_message(struct pri *ctrl, const char *fmt, va_list *ap)
- {
- char tmp[1024];
-- va_list ap;
-- va_start(ap, fmt);
-- vsnprintf(tmp, sizeof(tmp), fmt, ap);
-- va_end(ap);
-+
-+ vsnprintf(tmp, sizeof(tmp), fmt, *ap);
- if (__pri_message)
-- __pri_message(pri, tmp);
-+ __pri_message(ctrl, tmp);
- else
- fputs(tmp, stdout);
- }
-
--void pri_error(struct pri *pri, char *fmt, ...)
-+void pri_message(struct pri *ctrl, const char *fmt, ...)
- {
-+ int added_length;
-+ va_list ap;
-+
-+ ctrl = PRI_MASTER(ctrl);
-+ if (!ctrl || !ctrl->msg_line) {
-+ /* Just have to do it the old way. */
-+ va_start(ap, fmt);
-+ pri_old_message(ctrl, fmt, &ap);
-+ va_end(ap);
-+ return;
-+ }
-+
-+ va_start(ap, fmt);
-+ added_length = vsnprintf(ctrl->msg_line->str + ctrl->msg_line->length,
-+ sizeof(ctrl->msg_line->str) - ctrl->msg_line->length, fmt, ap);
-+ va_end(ap);
-+ if (added_length < 0
-+ || sizeof(ctrl->msg_line->str) <= ctrl->msg_line->length + added_length) {
-+ static char truncated_output[] =
-+ "v-- Error building output or output was truncated. (Next line) --v\n";
-+
-+ /*
-+ * This clause should never need to run because the
-+ * output line accumulation buffer is quite large.
-+ */
-+
-+ /* vsnprintf() error or output string was truncated. */
-+ if (__pri_message) {
-+ __pri_message(ctrl, truncated_output);
-+ } else {
-+ fputs(truncated_output, stdout);
-+ }
-+
-+ /* Add a terminating '\n' to force a flush of the line. */
-+ ctrl->msg_line->length = strlen(ctrl->msg_line->str);
-+ if (ctrl->msg_line->length) {
-+ ctrl->msg_line->str[ctrl->msg_line->length - 1] = '\n';
-+ } else {
-+ ctrl->msg_line->str[0] = '\n';
-+ ctrl->msg_line->str[1] = '\0';
-+ }
-+ } else {
-+ ctrl->msg_line->length += added_length;
-+ }
-+
-+ if (ctrl->msg_line->length
-+ && ctrl->msg_line->str[ctrl->msg_line->length - 1] == '\n') {
-+ /* The accumulated output line was terminated so send it out. */
-+ ctrl->msg_line->length = 0;
-+ if (__pri_message) {
-+ __pri_message(ctrl, ctrl->msg_line->str);
-+ } else {
-+ fputs(ctrl->msg_line->str, stdout);
-+ }
-+ }
-+}
-+
-+void pri_error(struct pri *pri, const char *fmt, ...)
-+{
- char tmp[1024];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(tmp, sizeof(tmp), fmt, ap);
- va_end(ap);
- if (__pri_error)
-- __pri_error(pri, tmp);
-+ __pri_error(PRI_MASTER(pri), tmp);
- else
- fputs(tmp, stderr);
- }
-@@ -821,49 +1235,102 @@
- return pri->fd;
- }
-
--char *pri_dump_info_str(struct pri *pri)
-+/*!
-+ * \internal
-+ * \brief Append snprintf output to the given buffer.
-+ *
-+ * \param buf Buffer currently filling.
-+ * \param buf_used Offset into buffer where to put new stuff.
-+ * \param buf_size Actual buffer size of buf.
-+ * \param format printf format string.
-+ *
-+ * \return Total buffer space used.
-+ */
-+static size_t pri_snprintf(char *buf, size_t buf_used, size_t buf_size, const char *format, ...) __attribute__((format(printf, 4, 5)));
-+static size_t pri_snprintf(char *buf, size_t buf_used, size_t buf_size, const char *format, ...)
- {
-- char buf[4096];
-- int len = 0;
-+ va_list args;
-+
-+ if (buf_used < buf_size) {
-+ va_start(args, format);
-+ buf_used += vsnprintf(buf + buf_used, buf_size - buf_used, format, args);
-+ va_end(args);
-+ }
-+ if (buf_size < buf_used) {
-+ buf_used = buf_size + 1;
-+ }
-+ return buf_used;
-+}
-+
-+char *pri_dump_info_str(struct pri *ctrl)
-+{
-+ char *buf;
-+ size_t buf_size;
-+ size_t used;
- #ifdef LIBPRI_COUNTERS
- struct q921_frame *f;
-- int q921outstanding = 0;
-+ unsigned q921outstanding;
- #endif
-- if (!pri)
-+ unsigned idx;
-+ unsigned long switch_bit;
-+
-+ if (!ctrl) {
- return NULL;
-+ }
-
-+ buf_size = 4096; /* This should be bigger than we will ever need. */
-+ buf = malloc(buf_size);
-+ if (!buf) {
-+ return NULL;
-+ }
-+
- /* Might be nice to format these a little better */
-- len += sprintf(buf + len, "Switchtype: %s\n", pri_switch2str(pri->switchtype));
-- len += sprintf(buf + len, "Type: %s\n", pri_node2str(pri->localtype));
-+ used = 0;
-+ used = pri_snprintf(buf, used, buf_size, "Switchtype: %s\n",
-+ pri_switch2str(ctrl->switchtype));
-+ used = pri_snprintf(buf, used, buf_size, "Type: %s\n", pri_node2str(ctrl->localtype));
- #ifdef LIBPRI_COUNTERS
- /* Remember that Q921 Counters include Q931 packets (and any retransmissions) */
-- len += sprintf(buf + len, "Q931 RX: %d\n", pri->q931_rxcount);
-- len += sprintf(buf + len, "Q931 TX: %d\n", pri->q931_txcount);
-- len += sprintf(buf + len, "Q921 RX: %d\n", pri->q921_rxcount);
-- len += sprintf(buf + len, "Q921 TX: %d\n", pri->q921_txcount);
-- f = pri->txqueue;
-+ used = pri_snprintf(buf, used, buf_size, "Q931 RX: %d\n", ctrl->q931_rxcount);
-+ used = pri_snprintf(buf, used, buf_size, "Q931 TX: %d\n", ctrl->q931_txcount);
-+ used = pri_snprintf(buf, used, buf_size, "Q921 RX: %d\n", ctrl->q921_rxcount);
-+ used = pri_snprintf(buf, used, buf_size, "Q921 TX: %d\n", ctrl->q921_txcount);
-+ q921outstanding = 0;
-+ f = ctrl->txqueue;
- while (f) {
- q921outstanding++;
- f = f->next;
- }
-- len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
-+ used = pri_snprintf(buf, used, buf_size, "Q921 Outstanding: %u\n", q921outstanding);
- #endif
-- len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
-- len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
-- len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
-- len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
-- len += sprintf(buf + len, "Busy: %d\n", pri->busy);
-- len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
-- len += sprintf(buf + len, "Logical Channel Mapping: %d\n", pri->chan_mapping_logical);
-- len += sprintf(buf + len, "T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]);
-- len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
-- len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]);
-- len += sprintf(buf + len, "T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]);
-- len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
-- len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
-- len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
-+ used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->windowlen,
-+ ctrl->window);
-+ used = pri_snprintf(buf, used, buf_size, "Sentrej: %d\n", ctrl->sentrej);
-+ used = pri_snprintf(buf, used, buf_size, "SolicitFbit: %d\n", ctrl->solicitfbit);
-+ used = pri_snprintf(buf, used, buf_size, "Retrans: %d\n", ctrl->retrans);
-+ used = pri_snprintf(buf, used, buf_size, "Busy: %d\n", ctrl->busy);
-+ used = pri_snprintf(buf, used, buf_size, "Overlap Dial: %d\n", ctrl->overlapdial);
-+ used = pri_snprintf(buf, used, buf_size, "Logical Channel Mapping: %d\n",
-+ ctrl->chan_mapping_logical);
-+ used = pri_snprintf(buf, used, buf_size, "Timer and counter settings:\n");
-+ switch_bit = PRI_BIT(ctrl->switchtype);
-+ for (idx = 0; idx < ARRAY_LEN(pri_timer); ++idx) {
-+ if (pri_timer[idx].used_by & switch_bit) {
-+ enum PRI_TIMERS_AND_COUNTERS tmr;
-
-- return strdup(buf);
-+ tmr = pri_timer[idx].number;
-+ if (0 <= ctrl->timers[tmr] || tmr == PRI_TIMER_T309) {
-+ used = pri_snprintf(buf, used, buf_size, " %s: %d\n",
-+ pri_timer[idx].name, ctrl->timers[tmr]);
-+ }
-+ }
-+ }
-+
-+ if (buf_size < used) {
-+ pri_message(ctrl,
-+ "pri_dump_info_str(): Produced output exceeded buffer capacity. (Truncated)\n");
-+ }
-+ return buf;
- }
-
- int pri_get_crv(struct pri *pri, q931_call *call, int *callmode)
-@@ -913,26 +1380,213 @@
-
- int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numcomplete)
- {
-- sr->called = called;
-- sr->calledplan = calledplan;
-+ q931_party_address_init(&sr->called);
-+ if (called) {
-+ sr->called.number.valid = 1;
-+ sr->called.number.plan = calledplan;
-+ libpri_copy_string(sr->called.number.str, called, sizeof(sr->called.number.str));
-+ }
- sr->numcomplete = numcomplete;
- return 0;
- }
-
-+void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
-+{
-+ pri_copy_party_subaddress_to_q931(&sr->called.subaddress, subaddress);
-+}
-+
- int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres)
- {
-- sr->caller = caller;
-- sr->callername = callername;
-- sr->callerplan = callerplan;
-- sr->callerpres = callerpres;
-+ q931_party_id_init(&sr->caller);
-+ if (caller) {
-+ sr->caller.number.valid = 1;
-+ sr->caller.number.presentation = callerpres;
-+ sr->caller.number.plan = callerplan;
-+ libpri_copy_string(sr->caller.number.str, caller, sizeof(sr->caller.number.str));
-+
-+ if (callername) {
-+ sr->caller.name.valid = 1;
-+ sr->caller.name.presentation = callerpres;
-+ sr->caller.name.char_set = PRI_CHAR_SET_ISO8859_1;
-+ libpri_copy_string(sr->caller.name.str, callername,
-+ sizeof(sr->caller.name.str));
-+ }
-+ }
- return 0;
- }
-
-+void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
-+{
-+ pri_copy_party_subaddress_to_q931(&sr->caller.subaddress, subaddress);
-+}
-+
-+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller)
-+{
-+ pri_copy_party_id_to_q931(&sr->caller, caller);
-+}
-+
- int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason)
- {
-- sr->redirectingnum = num;
-- sr->redirectingplan = plan;
-- sr->redirectingpres = pres;
-- sr->redirectingreason = reason;
-+ q931_party_redirecting_init(&sr->redirecting);
-+ if (num && num[0]) {
-+ sr->redirecting.from.number.valid = 1;
-+ sr->redirecting.from.number.presentation = pres;
-+ sr->redirecting.from.number.plan = plan;
-+ libpri_copy_string(sr->redirecting.from.number.str, num,
-+ sizeof(sr->redirecting.from.number.str));
-+
-+ sr->redirecting.count = 1;
-+ sr->redirecting.reason = reason;
-+ }
- return 0;
- }
-+
-+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting)
-+{
-+ pri_copy_party_id_to_q931(&sr->redirecting.from, &redirecting->from);
-+ pri_copy_party_id_to_q931(&sr->redirecting.to, &redirecting->to);
-+ pri_copy_party_id_to_q931(&sr->redirecting.orig_called, &redirecting->orig_called);
-+ sr->redirecting.orig_reason = redirecting->orig_reason;
-+ sr->redirecting.reason = redirecting->reason;
-+ if (redirecting->count <= 0) {
-+ if (sr->redirecting.from.number.valid) {
-+ /*
-+ * We are redirecting with an unknown count
-+ * so assume the count is one.
-+ */
-+ sr->redirecting.count = 1;
-+ } else {
-+ sr->redirecting.count = 0;
-+ }
-+ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
-+ sr->redirecting.count = redirecting->count;
-+ } else {
-+ sr->redirecting.count = PRI_MAX_REDIRECTS;
-+ }
-+}
-+
-+void pri_sr_set_reversecharge(struct pri_sr *sr, int requested)
-+{
-+ sr->reversecharge = requested;
-+}
-+
-+void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits)
-+{
-+ sr->keypad_digits = keypad_digits;
-+}
-+
-+void pri_hold_enable(struct pri *ctrl, int enable)
-+{
-+ ctrl = PRI_MASTER(ctrl);
-+ if (ctrl) {
-+ ctrl->hold_support = enable ? 1 : 0;
-+ }
-+}
-+
-+int pri_hold(struct pri *ctrl, q931_call *call)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_hold(ctrl, call);
-+}
-+
-+int pri_hold_ack(struct pri *ctrl, q931_call *call)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_hold_ack(ctrl, call);
-+}
-+
-+int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_hold_rej(ctrl, call, cause);
-+}
-+
-+int pri_retrieve(struct pri *ctrl, q931_call *call, int channel)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_retrieve(ctrl, call, channel);
-+}
-+
-+int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_retrieve_ack(ctrl, call, channel);
-+}
-+
-+int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_retrieve_rej(ctrl, call, cause);
-+}
-+
-+int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
-+{
-+ if (!pri || !call || !dest)
-+ return -1;
-+
-+ return qsig_cf_callrerouting(pri, call, dest, original, reason);
-+}
-+
-+void pri_reroute_enable(struct pri *ctrl, int enable)
-+{
-+ ctrl = PRI_MASTER(ctrl);
-+ if (ctrl) {
-+ ctrl->deflection_support = enable ? 1 : 0;
-+ }
-+}
-+
-+int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option)
-+{
-+ const struct q931_party_id *caller_id;
-+ struct q931_party_id local_caller;
-+ struct q931_party_redirecting reroute;
-+
-+ if (!ctrl || !call || !deflection) {
-+ return -1;
-+ }
-+
-+ if (caller) {
-+ /* Convert the caller update information. */
-+ pri_copy_party_id_to_q931(&local_caller, caller);
-+ q931_party_id_fixup(ctrl, &local_caller);
-+ caller_id = &local_caller;
-+ } else {
-+ caller_id = NULL;
-+ }
-+
-+ /* Convert the deflection information. */
-+ q931_party_redirecting_init(&reroute);
-+ pri_copy_party_id_to_q931(&reroute.from, &deflection->from);
-+ q931_party_id_fixup(ctrl, &reroute.from);
-+ pri_copy_party_id_to_q931(&reroute.to, &deflection->to);
-+ q931_party_id_fixup(ctrl, &reroute.to);
-+ pri_copy_party_id_to_q931(&reroute.orig_called, &deflection->orig_called);
-+ q931_party_id_fixup(ctrl, &reroute.orig_called);
-+ reroute.reason = deflection->reason;
-+ reroute.orig_reason = deflection->orig_reason;
-+ if (deflection->count <= 0) {
-+ /*
-+ * We are deflecting with an unknown count
-+ * so assume the count is one.
-+ */
-+ reroute.count = 1;
-+ } else if (deflection->count < PRI_MAX_REDIRECTS) {
-+ reroute.count = deflection->count;
-+ } else {
-+ reroute.count = PRI_MAX_REDIRECTS;
-+ }
-+
-+ return send_reroute_request(ctrl, call, caller_id, &reroute, subscription_option);
-+}
-Index: Makefile
-===================================================================
---- a/Makefile (.../tags/1.4.10.2) (revision 1357)
-+++ b/Makefile (.../branches/1.4) (revision 1357)
-@@ -41,15 +41,55 @@
-
- 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
--CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
-+STATIC_OBJS= \
-+ copy_string.o \
-+ pri.o \
-+ q921.o \
-+ prisched.o \
-+ q931.o \
-+ pri_facility.o \
-+ asn1_primitive.o \
-+ rose.o \
-+ rose_address.o \
-+ rose_etsi_aoc.o \
-+ rose_etsi_diversion.o \
-+ rose_etsi_ect.o \
-+ rose_other.o \
-+ rose_q931.o \
-+ rose_qsig_aoc.o \
-+ rose_qsig_ct.o \
-+ rose_qsig_diversion.o \
-+ rose_qsig_mwi.o \
-+ rose_qsig_name.o \
-+ version.o
-+DYNAMIC_OBJS= \
-+ copy_string.lo \
-+ pri.lo \
-+ q921.lo \
-+ prisched.lo \
-+ q931.lo \
-+ pri_facility.lo \
-+ asn1_primitive.lo \
-+ rose.lo \
-+ rose_address.lo \
-+ rose_etsi_aoc.lo \
-+ rose_etsi_diversion.lo \
-+ rose_etsi_ect.lo \
-+ rose_other.lo \
-+ rose_q931.lo \
-+ rose_qsig_aoc.lo \
-+ rose_qsig_ct.lo \
-+ rose_qsig_diversion.lo \
-+ rose_qsig_mwi.lo \
-+ rose_qsig_name.lo \
-+ version.lo
-+CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) $(LIBPRI_OPT)
- INSTALL_PREFIX=$(DESTDIR)
- INSTALL_BASE=/usr
- libdir?=$(INSTALL_BASE)/lib
- SOFLAGS:=-Wl,-h$(DYNAMIC_LIBRARY)
- LDCONFIG = /sbin/ldconfig
--ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
-+ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX XGNUX))
- LDCONFIG_FLAGS=-n
- else
- ifeq (${OSARCH},FreeBSD)
-@@ -74,7 +114,9 @@
- #A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesnt support it.
- ifeq ($(PROC),sparc64)
- PROC=ultrasparc
--CFLAGS += -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
-+LIBPRI_OPT = -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
-+else
-+LIBPRI_OPT = -O2
- endif
-
- all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
-@@ -132,6 +174,9 @@
- 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
-Index: q931.c
-===================================================================
---- a/q931.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/q931.c (.../branches/1.4) (revision 1357)
-@@ -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>
-@@ -67,7 +68,7 @@
- { Q931_RESTART_ACKNOWLEDGE, "RESTART ACKNOWLEDGE", { Q931_RESTART_INDICATOR } },
-
- /* Miscellaneous */
-- { Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_CALL_STATE } },
-+ { Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_IE_CALL_STATE } },
- { Q931_STATUS_ENQUIRY, "STATUS ENQUIRY" },
- { Q931_USER_INFORMATION, "USER_INFORMATION" },
- { Q931_SEGMENT, "SEGMENT" },
-@@ -79,22 +80,32 @@
- /* Call Management */
- { Q931_HOLD, "HOLD" },
- { Q931_HOLD_ACKNOWLEDGE, "HOLD ACKNOWLEDGE" },
-- { Q931_HOLD_REJECT, "HOLD REJECT" },
-+ { Q931_HOLD_REJECT, "HOLD REJECT", { Q931_CAUSE } },
- { Q931_RETRIEVE, "RETRIEVE" },
- { Q931_RETRIEVE_ACKNOWLEDGE, "RETRIEVE ACKNOWLEDGE" },
-- { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT" },
-+ { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT", { Q931_CAUSE } },
- { Q931_RESUME, "RESUME" },
- { Q931_RESUME_ACKNOWLEDGE, "RESUME ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
- { Q931_RESUME_REJECT, "RESUME REJECT", { Q931_CAUSE } },
- { Q931_SUSPEND, "SUSPEND" },
- { Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
- { Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
-+};
-
-- /* Maintenance */
-- { NATIONAL_SERVICE, "SERVICE" },
-- { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" },
-+static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand);
-+static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int *allow_event, int *allow_posthandle);
-+
-+struct msgtype att_maintenance_msgs[] = {
-+ { ATT_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
-+ { ATT_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
- };
-
-+struct msgtype national_maintenance_msgs[] = {
-+ { NATIONAL_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
-+ { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
-+};
-+static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, struct q931_mh *mh, struct q931_call *c);
-+
- static struct msgtype causes[] = {
- { PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" },
- { PRI_CAUSE_NO_ROUTE_TRANSIT_NET, "No route to specified transmit network" },
-@@ -107,6 +118,7 @@
- { PRI_CAUSE_NO_ANSWER, "User alerting, no answer" },
- { PRI_CAUSE_CALL_REJECTED, "Call Rejected" },
- { PRI_CAUSE_NUMBER_CHANGED, "Number changed" },
-+ { PRI_CAUSE_NONSELECTED_USER_CLEARING, "Non-selected user clearing" },
- { PRI_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order" },
- { PRI_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format" },
- { PRI_CAUSE_FACILITY_REJECTED, "Facility rejected" },
-@@ -119,13 +131,14 @@
- { PRI_CAUSE_ACCESS_INFO_DISCARDED, "Access information discarded" },
- { PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel not available" },
- { PRI_CAUSE_PRE_EMPTED, "Pre-empted" },
-+ { PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED, "Resource unavailable, unspecified" },
- { PRI_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed" },
- { PRI_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred" },
- { PRI_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred" },
- { PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" },
- { PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" },
-+ { PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
- { PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" },
-- { PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
- { PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" },
- { PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" },
- { PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" },
-@@ -163,8 +176,9 @@
- { PRI_NSF_CALL_REDIRECTION_SERVICE, "Call Redirection Service" }
- };
-
--#define FLAG_PREFERRED 2
--#define FLAG_EXCLUSIVE 4
-+#define FLAG_WHOLE_INTERFACE 0x01
-+#define FLAG_PREFERRED 0x02
-+#define FLAG_EXCLUSIVE 0x04
-
- #define RESET_INDICATOR_CHANNEL 0
- #define RESET_INDICATOR_DS1 6
-@@ -214,26 +228,49 @@
- #define LOC_NETWORK_BEYOND_INTERWORKING 0xa
-
- static char *ie2str(int ie);
--static char *msg2str(int msg);
-
-
--#define FUNC_DUMP(name) void ((name))(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
--#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
--#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+#define FUNC_DUMP(name) void (name)(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
-+#define FUNC_RECV(name) int (name)(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+#define FUNC_SEND(name) int (name)(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-
- #if 1
- /* Update call state with transition trace. */
--#define UPDATE_OURCALLSTATE(pri,c,newstate) do {\
-- if (pri->debug & (PRI_DEBUG_Q931_STATE) && c->ourcallstate != newstate) \
-- pri_message(pri, DBGHEAD "call %d on channel %d enters state %d (%s)\n", DBGINFO, \
-- c->cr, c->channelno, newstate, callstate2str(newstate)); \
-- c->ourcallstate = newstate; \
-+#define UPDATE_OURCALLSTATE(ctrl, call, newstate) \
-+ do { \
-+ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) && (call)->ourcallstate != (newstate)) { \
-+ pri_message((ctrl), \
-+ DBGHEAD "%s %d enters state %d (%s). Hold state: %s\n", \
-+ DBGINFO, ((call) == (call)->master_call) ? "Call" : "Subcall", \
-+ (call)->cr, (newstate), q931_call_state_str(newstate), \
-+ q931_hold_state_str((call)->master_call->hold_state)); \
-+ } \
-+ (call)->ourcallstate = (newstate); \
- } while (0)
- #else
- /* Update call state with no trace. */
--#define UPDATE_OURCALLSTATE(pri,c,newstate) c->ourcallstate = newstate
-+#define UPDATE_OURCALLSTATE(ctrl, call, newstate) (call)->ourcallstate = (newstate)
- #endif
-
-+#if 1
-+/* Update hold state with transition trace. */
-+#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) \
-+ do { \
-+ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) \
-+ && (master_call)->hold_state != (newstate)) { \
-+ pri_message((ctrl), \
-+ DBGHEAD "Call %d in state %d (%s) enters Hold state: %s\n", \
-+ DBGINFO, (master_call)->cr, (master_call)->ourcallstate, \
-+ q931_call_state_str((master_call)->ourcallstate), \
-+ q931_hold_state_str(newstate)); \
-+ } \
-+ (master_call)->hold_state = (newstate); \
-+ } while (0)
-+#else
-+/* Update hold state with no trace. */
-+#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) (master_call)->hold_state = (newstate)
-+#endif
-+
- struct ie {
- /* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
- int max_count;
-@@ -249,6 +286,506 @@
- FUNC_SEND(*transmit);
- };
-
-+/*!
-+ * \internal
-+ * \brief Encode the channel id information to pass to upper level.
-+ *
-+ * \param call Q.931 call leg
-+ *
-+ * \return Encoded channel value.
-+ */
-+static int q931_encode_channel(const q931_call *call)
-+{
-+ int held_call;
-+ int channelno;
-+ int ds1no;
-+
-+ switch (call->master_call->hold_state) {
-+ case Q931_HOLD_STATE_CALL_HELD:
-+ case Q931_HOLD_STATE_RETRIEVE_REQ:
-+ case Q931_HOLD_STATE_RETRIEVE_IND:
-+ held_call = 1 << 18;
-+
-+ /* So a -1 does not wipe out the held_call flag. */
-+ channelno = call->channelno & 0xFF;
-+ ds1no = call->ds1no & 0xFF;
-+ break;
-+ default:
-+ held_call = 0;
-+ channelno = call->channelno;
-+ ds1no = call->ds1no;
-+ break;
-+ }
-+ return channelno | (ds1no << 8) | (call->ds1explicit << 16) | (call->cis_call << 17)
-+ | held_call;
-+}
-+
-+/*!
-+ * \brief Determine if layer 2 is in PTMP mode.
-+ *
-+ * \param ctrl D channel controller.
-+ *
-+ * \retval TRUE if in PTMP mode.
-+ * \retval FALSE otherwise.
-+ */
-+int q931_is_ptmp(const struct pri *ctrl)
-+{
-+ /* Check master control structure */
-+ for (; ctrl->master; ctrl = ctrl->master) {
-+ }
-+ return ctrl->tei == Q921_TEI_GROUP;
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_name
-+ *
-+ * \param name Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_name_init(struct q931_party_name *name)
-+{
-+ name->valid = 0;
-+ name->presentation = PRI_PRES_UNAVAILABLE;
-+ name->char_set = PRI_CHAR_SET_ISO8859_1;
-+ name->str[0] = '\0';
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_number
-+ *
-+ * \param number Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_number_init(struct q931_party_number *number)
-+{
-+ number->valid = 0;
-+ number->presentation = PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ number->plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ number->str[0] = '\0';
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_subaddress
-+ *
-+ * \param subaddress Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_subaddress_init(struct q931_party_subaddress *subaddress)
-+{
-+ subaddress->valid = 0;
-+ subaddress->type = 0;
-+ subaddress->odd_even_indicator = 0;
-+ subaddress->length = 0;
-+ subaddress->data[0] = '\0';
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_address
-+ *
-+ * \param address Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_address_init(struct q931_party_address *address)
-+{
-+ q931_party_number_init(&address->number);
-+ q931_party_subaddress_init(&address->subaddress);
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_id
-+ *
-+ * \param id Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_id_init(struct q931_party_id *id)
-+{
-+ q931_party_name_init(&id->name);
-+ q931_party_number_init(&id->number);
-+ q931_party_subaddress_init(&id->subaddress);
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_redirecting
-+ *
-+ * \param redirecting Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_redirecting_init(struct q931_party_redirecting *redirecting)
-+{
-+ q931_party_id_init(&redirecting->from);
-+ q931_party_id_init(&redirecting->to);
-+ q931_party_id_init(&redirecting->orig_called);
-+ redirecting->state = Q931_REDIRECTING_STATE_IDLE;
-+ redirecting->count = 0;
-+ redirecting->orig_reason = PRI_REDIR_UNKNOWN;
-+ redirecting->reason = PRI_REDIR_UNKNOWN;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party name.
-+ *
-+ * \param left Left parameter party name.
-+ * \param right Right parameter party name.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right)
-+{
-+ int cmp;
-+
-+ if (!left->valid) {
-+ if (!right->valid) {
-+ return 0;
-+ }
-+ return -1;
-+ } else if (!right->valid) {
-+ return 1;
-+ }
-+ cmp = left->char_set - right->char_set;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = strcmp(left->str, right->str);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->presentation - right->presentation;
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party number.
-+ *
-+ * \param left Left parameter party number.
-+ * \param right Right parameter party number.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right)
-+{
-+ int cmp;
-+
-+ if (!left->valid) {
-+ if (!right->valid) {
-+ return 0;
-+ }
-+ return -1;
-+ } else if (!right->valid) {
-+ return 1;
-+ }
-+ cmp = left->plan - right->plan;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = strcmp(left->str, right->str);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->presentation - right->presentation;
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party subaddress.
-+ *
-+ * \param left Left parameter party subaddress.
-+ * \param right Right parameter party subaddress.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right)
-+{
-+ int cmp;
-+
-+ if (!left->valid) {
-+ if (!right->valid) {
-+ return 0;
-+ }
-+ return -1;
-+ } else if (!right->valid) {
-+ return 1;
-+ }
-+ cmp = left->type - right->type;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = memcmp(left->data, right->data,
-+ (left->length < right->length) ? left->length : right->length);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->length - right->length;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->odd_even_indicator - right->odd_even_indicator;
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party id.
-+ *
-+ * \param left Left parameter party id.
-+ * \param right Right parameter party id.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right)
-+{
-+ int cmp;
-+
-+ cmp = q931_party_number_cmp(&left->number, &right->number);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = q931_party_subaddress_cmp(&left->subaddress, &right->subaddress);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = q931_party_name_cmp(&left->name, &right->name);
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party name to the PRI party name structure.
-+ *
-+ * \param pri_name PRI party name structure
-+ * \param q931_name Q.931 party name structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name)
-+{
-+ if (q931_name->valid) {
-+ pri_name->valid = 1;
-+ pri_name->presentation = q931_name->presentation;
-+ pri_name->char_set = q931_name->char_set;
-+ libpri_copy_string(pri_name->str, q931_name->str, sizeof(pri_name->str));
-+ } else {
-+ pri_name->valid = 0;
-+ pri_name->presentation = PRI_PRES_UNAVAILABLE;
-+ pri_name->char_set = PRI_CHAR_SET_ISO8859_1;
-+ pri_name->str[0] = 0;
-+ }
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party number to the PRI party number structure.
-+ *
-+ * \param pri_number PRI party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number)
-+{
-+ if (q931_number->valid) {
-+ pri_number->valid = 1;
-+ pri_number->presentation = q931_number->presentation;
-+ pri_number->plan = q931_number->plan;
-+ libpri_copy_string(pri_number->str, q931_number->str, sizeof(pri_number->str));
-+ } else {
-+ pri_number->valid = 0;
-+ pri_number->presentation = PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ pri_number->plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ pri_number->str[0] = 0;
-+ }
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party subaddress to the PRI party subaddress structure.
-+ *
-+ * \param pri_subaddress PRI party subaddress structure
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress)
-+{
-+ int length;
-+
-+ /*
-+ * The size of pri_subaddress->data[] is not the same as the size of
-+ * q931_subaddress->data[].
-+ */
-+
-+ if (!q931_subaddress->valid) {
-+ pri_subaddress->valid = 0;
-+ pri_subaddress->type = 0;
-+ pri_subaddress->odd_even_indicator = 0;
-+ pri_subaddress->length = 0;
-+ pri_subaddress->data[0] = '\0';
-+ return;
-+ }
-+
-+ pri_subaddress->valid = 1;
-+ pri_subaddress->type = q931_subaddress->type;
-+ pri_subaddress->odd_even_indicator = q931_subaddress->odd_even_indicator;
-+
-+ length = q931_subaddress->length;
-+ pri_subaddress->length = length;
-+ memcpy(pri_subaddress->data, q931_subaddress->data, length);
-+ pri_subaddress->data[length] = '\0';
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party id to the PRI party id structure.
-+ *
-+ * \param pri_id PRI party id structure
-+ * \param q931_id Q.931 party id structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id)
-+{
-+ q931_party_name_copy_to_pri(&pri_id->name, &q931_id->name);
-+ q931_party_number_copy_to_pri(&pri_id->number, &q931_id->number);
-+ q931_party_subaddress_copy_to_pri(&pri_id->subaddress, &q931_id->subaddress);
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 redirecting data to the PRI redirecting structure.
-+ *
-+ * \param pri_redirecting PRI redirecting structure
-+ * \param q931_redirecting Q.931 redirecting structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting)
-+{
-+ q931_party_id_copy_to_pri(&pri_redirecting->from, &q931_redirecting->from);
-+ q931_party_id_copy_to_pri(&pri_redirecting->to, &q931_redirecting->to);
-+ q931_party_id_copy_to_pri(&pri_redirecting->orig_called,
-+ &q931_redirecting->orig_called);
-+ pri_redirecting->count = q931_redirecting->count;
-+ pri_redirecting->orig_reason = q931_redirecting->orig_reason;
-+ pri_redirecting->reason = q931_redirecting->reason;
-+}
-+
-+/*!
-+ * \brief Fixup some values in the q931_party_id that may be objectionable by switches.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param id Party ID to tweak.
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id)
-+{
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ case PRI_SWITCH_ATT4ESS:
-+ /* Doesn't like certain presentation types */
-+ if (id->number.valid && !(id->number.presentation & 0x7c)) {
-+ /* i.e., If presentation is allowed it must be a network number */
-+ id->number.presentation = PRES_ALLOWED_NETWORK_NUMBER;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/*!
-+ * \brief Determine the overall presentation value for the given party.
-+ *
-+ * \param id Party to determine the overall presentation value.
-+ *
-+ * \return Overall presentation value for the given party.
-+ */
-+int q931_party_id_presentation(const struct q931_party_id *id)
-+{
-+ int number_priority;
-+ int number_value;
-+ int number_screening;
-+ int name_priority;
-+ int name_value;
-+
-+ /* Determine name presentation priority. */
-+ if (!id->name.valid) {
-+ name_value = PRI_PRES_UNAVAILABLE;
-+ name_priority = 3;
-+ } else {
-+ name_value = id->name.presentation & PRI_PRES_RESTRICTION;
-+ switch (name_value) {
-+ case PRI_PRES_RESTRICTED:
-+ name_priority = 0;
-+ break;
-+ case PRI_PRES_ALLOWED:
-+ name_priority = 1;
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ name_priority = 2;
-+ break;
-+ default:
-+ name_value = PRI_PRES_UNAVAILABLE;
-+ name_priority = 3;
-+ break;
-+ }
-+ }
-+
-+ /* Determine number presentation priority. */
-+ if (!id->number.valid) {
-+ number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
-+ number_value = PRI_PRES_UNAVAILABLE;
-+ number_priority = 3;
-+ } else {
-+ number_screening = id->number.presentation & PRI_PRES_NUMBER_TYPE;
-+ number_value = id->number.presentation & PRI_PRES_RESTRICTION;
-+ switch (number_value) {
-+ case PRI_PRES_RESTRICTED:
-+ number_priority = 0;
-+ break;
-+ case PRI_PRES_ALLOWED:
-+ number_priority = 1;
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ number_priority = 2;
-+ break;
-+ default:
-+ number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
-+ number_value = PRI_PRES_UNAVAILABLE;
-+ number_priority = 3;
-+ break;
-+ }
-+ }
-+
-+ /* Select the wining presentation value. */
-+ if (name_priority < number_priority) {
-+ number_value = name_value;
-+ }
-+
-+ return number_value | number_screening;
-+}
-+
-+static void q931_clr_subcommands(struct pri *ctrl)
-+{
-+ ctrl->subcmds.counter_subcmd = 0;
-+}
-+
-+struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl)
-+{
-+ if (ctrl->subcmds.counter_subcmd < PRI_MAX_SUBCOMMANDS) {
-+ return &ctrl->subcmds.subcmd[ctrl->subcmds.counter_subcmd++];
-+ }
-+
-+ return NULL;
-+}
-+
- static char *code2str(int code, struct msgtype *codes, int max)
- {
- int x;
-@@ -258,15 +795,18 @@
- return "Unknown";
- }
-
--static void call_init(struct q931_call *c)
-+static char *pritype(int type)
- {
-- c->forceinvert = -1;
-- c->cr = -1;
-- c->slotmap = -1;
-- c->channelno = -1;
-- c->newcall = 1;
-- c->ourcallstate = Q931_CALL_STATE_NULL;
-- c->peercallstate = Q931_CALL_STATE_NULL;
-+ switch (type) {
-+ case PRI_CPE:
-+ return "CPE";
-+ break;
-+ case PRI_NETWORK:
-+ return "NET";
-+ break;
-+ default:
-+ return "UNKNOWN";
-+ }
- }
-
- static char *binary(int b, int len) {
-@@ -280,56 +820,85 @@
- return res;
- }
-
--static FUNC_RECV(receive_channel_id)
-+static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int x;
-- int pos=0;
--#ifdef NO_BRI_SUPPORT
-- if (!ie->data[0] & 0x20) {
-- pri_error(pri, "!! Not PRI type!?\n");
-- return -1;
-- }
--#endif
--#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
-- if (pri->bri) {
-- if (!(ie->data[0] & 3))
-- call->justsignalling = 1;
-- else
-- call->channelno = ie->data[0] & 3;
-+ int pos = 0;
-+ int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
-+
-+ if (ie->data[0] & 0x08) {
-+ call->chanflags = FLAG_EXCLUSIVE;
- } else {
-- switch (ie->data[0] & 3) {
-- case 0:
-- call->justsignalling = 1;
-- break;
-- case 1:
-- break;
-- default:
-- pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
-- return -1;
-+ call->chanflags = FLAG_PREFERRED;
-+ }
-+
-+ need_extended_channel_octets = 0;
-+ if (ie->data[0] & 0x20) {
-+ /* PRI encoded interface type */
-+ switch (ie->data[0] & 0x03) {
-+ case 0x00:
-+ /* No channel */
-+ call->channelno = 0;
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ case 0x01:
-+ /* As indicated in following octets */
-+ need_extended_channel_octets = 1;
-+ break;
-+ case 0x03:
-+ /* Any channel */
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ default:
-+ pri_error(ctrl, "!! Unexpected Channel selection %d\n", ie->data[0] & 0x03);
-+ return -1;
- }
-+ } else {
-+ /* BRI encoded interface type */
-+ switch (ie->data[0] & 0x03) {
-+ case 0x00:
-+ /* No channel */
-+ call->channelno = 0;
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ case 0x03:
-+ /* Any channel */
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ default:
-+ /* Specified B channel (B1 or B2) */
-+ call->channelno = ie->data[0] & 0x03;
-+ break;
-+ }
- }
--#endif
-- if (ie->data[0] & 0x08)
-- call->chanflags = FLAG_EXCLUSIVE;
-- else
-- call->chanflags = FLAG_PREFERRED;
-+
- pos++;
- if (ie->data[0] & 0x40) {
- /* DS1 specified -- stop here */
- call->ds1no = ie->data[1] & 0x7f;
- call->ds1explicit = 1;
- pos++;
-- } else
-+ } else {
- call->ds1explicit = 0;
-+ }
-
-- if (pos+2 < len) {
-+ if (ie->data[0] & 0x04) {
-+ /* D channel call. Signaling only. */
-+ call->cis_call = 1;
-+ call->chanflags = FLAG_EXCLUSIVE;/* For safety mark this channel as exclusive. */
-+ call->channelno = 0;
-+ return 0;
-+ }
-+
-+ if (need_extended_channel_octets && pos + 2 < len) {
- /* More coming */
- if ((ie->data[pos] & 0x0f) != 3) {
-- pri_error(pri, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
-+ /* Channel type/mapping is not for B channel units. */
-+ pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
- return -1;
- }
- if ((ie->data[pos] & 0x60) != 0) {
-- pri_error(pri, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
-+ pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
- return -1;
- }
- if (ie->data[pos] & 0x10) {
-@@ -340,136 +909,167 @@
- call->slotmap <<= 8;
- call->slotmap |= ie->data[x + pos];
- }
-- return 0;
- } else {
- pos++;
- /* Only expect a particular channel */
- call->channelno = ie->data[pos] & 0x7f;
-- if (pri->chan_mapping_logical && call->channelno > 15)
-+ if (ctrl->chan_mapping_logical && call->channelno > 15)
- call->channelno++;
-- return 0;
- }
-- } else
-- return 0;
-- return -1;
-+ }
-+ return 0;
- }
-
--static FUNC_SEND(transmit_channel_id)
-+static int transmit_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- int pos=0;
-+ int pos = 0;
-
--
- /* We are ready to transmit single IE only */
- if (order > 1)
- return 0;
--
-- if (call->justsignalling) {
-- ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
-- ECMA-165 section 7.3 */
-+
-+ if (call->cis_call) {
-+ /*
-+ * Read the standards docs to figure this out.
-+ * Q.SIG ECMA-165 section 7.3
-+ * ITU Q.931 section 4.5.13
-+ */
-+ ie->data[pos++] = ctrl->bri ? 0x8c : 0xac;
- return pos + 2;
- }
--
-+
- /* Start with standard stuff */
-- if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-+ if (ctrl->switchtype == PRI_SWITCH_GR303_TMC)
- ie->data[pos] = 0x69;
-- else if (pri->bri) {
-+ else if (ctrl->bri) {
- ie->data[pos] = 0x80;
-- if (call->channelno > -1)
-- ie->data[pos] |= (call->channelno & 0x3);
-- } else
-- ie->data[pos] = 0xa1;
-- /* Add exclusive flag if necessary */
-- if (call->chanflags & FLAG_EXCLUSIVE)
-+ ie->data[pos] |= (call->channelno & 0x3);
-+ } else {
-+ /* PRI */
-+ if (call->slotmap != -1 || (call->chanflags & FLAG_WHOLE_INTERFACE)) {
-+ /* Specified channel */
-+ ie->data[pos] = 0xa1;
-+ } else if (call->channelno < 0 || call->channelno == 0xff) {
-+ /* Any channel */
-+ ie->data[pos] = 0xa3;
-+ } else if (!call->channelno) {
-+ /* No channel */
-+ ie->data[pos] = 0xa0;
-+ } else {
-+ /* Specified channel */
-+ ie->data[pos] = 0xa1;
-+ }
-+ }
-+ if (call->chanflags & FLAG_EXCLUSIVE) {
-+ /* Channel is exclusive */
- ie->data[pos] |= 0x08;
-- else if (!(call->chanflags & FLAG_PREFERRED)) {
-+ } else if (!call->chanflags) {
- /* Don't need this IE */
- return 0;
- }
-
-- if (((pri->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit) {
-- /* Note that we are specifying the identifier */
-+ if (!ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
-+ /* We are specifying the interface. Octet 3.1 */
- ie->data[pos++] |= 0x40;
-- /* We need to use the Channel Identifier Present thingy. Just specify it and we're done */
- ie->data[pos++] = 0x80 | call->ds1no;
-- } else
-- pos++;
-+ } else {
-+ ++pos;
-+ }
-
-- if (pri->bri)
-- return pos + 2;
-+ if (!ctrl->bri && (ie->data[0] & 0x03) == 0x01 /* Specified channel */
-+ && !(call->chanflags & FLAG_WHOLE_INTERFACE)) {
-+ /* The 3.2 and 3.3 octets need to be present */
-+ ie->data[pos] = 0x83;
-+ if (call->slotmap != -1) {
-+ int octet;
-
-- if ((call->channelno > -1) || (call->slotmap != -1)) {
-- /* We'll have the octet 8.2 and 8.3's present */
-- ie->data[pos++] = 0x83;
-- if (call->channelno > -1) {
-+ /* We have to send a channel map */
-+ ie->data[pos++] |= 0x10;
-+ for (octet = 3; octet--;) {
-+ ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
-+ }
-+ } else {
- /* Channel number specified */
-- if (pri->chan_mapping_logical && call->channelno > 16)
-+ ++pos;
-+ if (ctrl->chan_mapping_logical && call->channelno > 16) {
- ie->data[pos++] = 0x80 | (call->channelno - 1);
-- else
-+ } else {
- ie->data[pos++] = 0x80 | call->channelno;
-- return pos + 2;
-+ }
- }
-- /* We have to send a channel map */
-- if (call->slotmap != -1) {
-- ie->data[pos-1] |= 0x10;
-- ie->data[pos++] = (call->slotmap & 0xff0000) >> 16;
-- ie->data[pos++] = (call->slotmap & 0xff00) >> 8;
-- ie->data[pos++] = (call->slotmap & 0xff);
-- return pos + 2;
-- }
- }
-- if (call->ds1no > 0) {
-- /* We're done */
-- return pos + 2;
-- }
-- pri_error(pri, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
-- return -1;
-+
-+ return pos + 2;
- }
-
--static FUNC_DUMP(dump_channel_id)
-+static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- int pos=0;
-+ int pos;
- int x;
-- int res = 0;
-- static const char* msg_chan_sel[] = {
-- "No channel selected", "B1 channel", "B2 channel","Any channel selected",
-- "No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
-+ int res;
-+
-+ static const char *msg_chan_sel[] = {
-+ "No channel selected", "B1 channel", "B2 channel", "Any channel selected",
-+ "No channel selected", "As indicated in following octets", "Reserved", "Any channel selected"
- };
-
-- pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
-- prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
-- (ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
-- (ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0);
-- pri_message(pri, "%c ChanSel: %s\n",
-- prefix, msg_chan_sel[(ie->data[0] & 0x3) + ((ie->data[0]>>3) & 0x4)]);
-- pos++;
-- len--;
-- if (ie->data[0] & 0x40) {
-+ pri_message(ctrl,
-+ "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
-+ prefix, len,
-+ (ie->data[0] & 0x80) ? 1 : 0,
-+ (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
-+ (ie->data[0] & 0x20) ? "Other(PRI)" : "BRI",
-+ (ie->data[0] & 0x10) ? 1 : 0,
-+ (ie->data[0] & 0x08) ? "Exclusive" : "Preferred",
-+ (ie->data[0] & 0x04) ? 1 : 0);
-+ pri_message(ctrl, "%c ChanSel: %s\n",
-+ prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] >> 3) & 0x04)]);
-+ pos = 1;
-+ len -= 2;
-+ if (ie->data[0] & 0x40) {
- /* Explicitly defined DS1 */
-- pri_message(pri, "%c Ext: %d DS1 Identifier: %d \n", prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
-- pos++;
-+ do {
-+ pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d \n",
-+ prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
-+ ++pos;
-+ } while (!(ie->data[pos - 1] & 0x80) && pos < len);
- } else {
- /* Implicitly defined DS1 */
- }
-- if (pos+2 < len) {
-+ if (pos < len) {
- /* Still more information here */
-- pri_message(pri, "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
-- prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
-- (ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
-- if (!(ie->data[pos] & 0x10)) {
-+ pri_message(ctrl,
-+ "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
-+ prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
-+ (ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
-+ ++pos;
-+ }
-+ if (pos < len) {
-+ if (!(ie->data[pos - 1] & 0x10)) {
- /* Number specified */
-- pos++;
-- pri_message(pri, "%c Ext: %d Channel: %d ]\n", prefix, (ie->data[pos] & 0x80) >> 7,
-- (ie->data[pos]) & 0x7f);
-+ do {
-+ pri_message(ctrl,
-+ "%c Ext: %d Channel: %d Type: %s%c\n",
-+ prefix, (ie->data[pos] & 0x80) >> 7,
-+ (ie->data[pos]) & 0x7f, pritype(ctrl->localtype),
-+ (pos + 1 < len) ? ' ' : ']');
-+ ++pos;
-+ } while (pos < len);
- } else {
-- pos++;
- /* Map specified */
-- for (x=0;x<3;x++) {
-+ res = 0;
-+ x = 0;
-+ do {
- res <<= 8;
- res |= ie->data[pos++];
-- }
-- pri_message(pri, "%c Map: %s ]\n", prefix, binary(res, 24));
-+ ++x;
-+ } while (pos < len);
-+ pri_message(ctrl, "%c Map len: %d Map: %s ]\n", prefix,
-+ x, binary(res, x << 3));
- }
-- } else pri_message(pri, " ]\n");
-+ } else {
-+ pri_message(ctrl, " ]\n");
-+ }
- }
-
- static char *ri2str(int ri)
-@@ -482,20 +1082,20 @@
- return code2str(ri, ris, sizeof(ris) / sizeof(ris[0]));
- }
-
--static FUNC_DUMP(dump_restart_indicator)
-+static void dump_restart_indicator(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Restart Indentifier (len=%2d) [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
-+ pri_message(ctrl, "%c Restart Indentifier (len=%2d) [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
- prefix, len, (ie->data[0] & 0x80) >> 7, (ie->data[0] & 0x78) >> 3, ri2str(ie->data[0] & 0x7), ie->data[0] & 0x7);
- }
-
--static FUNC_RECV(receive_restart_indicator)
-+static int receive_restart_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- /* Pretty simple */
- call->ri = ie->data[0] & 0x7;
- return 0;
- }
-
--static FUNC_SEND(transmit_restart_indicator)
-+static int transmit_restart_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- /* Pretty simple */
- switch(call->ri) {
-@@ -509,7 +1109,7 @@
- ie->data[0] = 0xA0 | (call->ri & 0x7);
- break;
- default:
-- pri_error(pri, "!! Invalid restart indicator value %d\n", call->ri);
-+ pri_error(ctrl, "!! Invalid restart indicator value %d\n", call->ri);
- return-1;
- }
- return 3;
-@@ -607,16 +1207,16 @@
- return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
- }
-
--static FUNC_DUMP(dump_bearer_capability)
-+static void dump_bearer_capability(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int pos=2;
-- pri_message(pri, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
-+ pri_message(ctrl, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
- prefix, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
-- pri_message(pri, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
-+ pri_message(ctrl, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
-
- /* octet 4.1 exists iff mode/rate is multirate */
- if ((ie->data[1] & 0x7f) == 0x18) {
-- pri_message(pri, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
-+ pri_message(ctrl, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
- pos++;
- }
-
-@@ -632,7 +1232,7 @@
- too, so we have to do the same for binary compatability */
- u_int8_t layer1 = ie->data[pos] & 0x7f;
-
-- pri_message(pri, "%c User information layer 1: %s (%d)\n",
-+ pri_message(ctrl, "%c User information layer 1: %s (%d)\n",
- prefix, l12str(layer1), layer1);
- pos++;
-
-@@ -640,7 +1240,7 @@
- if (pos < len && !(ie->data[pos-1] & 0x80)) {
- int ra = ie->data[pos] & 0x7f;
-
-- pri_message(pri, "%c Async: %d, Negotiation: %d, "
-+ pri_message(ctrl, "%c Async: %d, Negotiation: %d, "
- "User rate: %s (%#x)\n",
- prefix,
- ra & PRI_RATE_ADAPT_ASYNC ? 1 : 0,
-@@ -654,7 +1254,7 @@
- if (pos < len && !(ie->data[pos-1] & 0x80)) {
- u_int8_t data = ie->data[pos];
- if (layer1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
-- pri_message(pri, "%c Intermediate rate: %s (%d), "
-+ pri_message(ctrl, "%c Intermediate rate: %s (%d), "
- "NIC on Tx: %d, NIC on Rx: %d, "
- "Flow control on Tx: %d, "
- "Flow control on Rx: %d\n",
-@@ -665,7 +1265,7 @@
- (data & 0x04)?1:0,
- (data & 0x02)?1:0);
- } else if (layer1 == PRI_LAYER_1_V120_RATE_ADAPT) {
-- pri_message(pri, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
-+ pri_message(ctrl, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
- "LLI negot: %d, Assignor: %d, "
- "In-band neg: %d\n", prefix,
- (data & 0x40)?1:0,
-@@ -675,7 +1275,8 @@
- (data & 0x04)?1:0,
- (data & 0x02)?1:0);
- } else {
-- pri_message(pri, "%c Unknown octet 5b: 0x%x\n", data );
-+ pri_message(ctrl, "%c Unknown octet 5b: 0x%x\n",
-+ prefix, data);
- }
- pos++;
- }
-@@ -688,7 +1289,7 @@
- const char *parity[] = {"Odd","?","Even","None",
- "zero","one","?","?"};
-
-- pri_message(pri, "%c Stop bits: %s, data bits: %s, "
-+ pri_message(ctrl, "%c Stop bits: %s, data bits: %s, "
- "parity: %s\n", prefix,
- stop_bits[(data & 0x60) >> 5],
- data_bits[(data & 0x18) >> 3],
-@@ -700,7 +1301,7 @@
- /* octet 5d? */
- if (pos < len && !(ie->data[pos-1] & 0x80)) {
- u_int8_t data = ie->data[pos];
-- pri_message(pri, "%c Duplex mode: %d, modem type: %d\n",
-+ pri_message(ctrl, "%c Duplex mode: %d, modem type: %d\n",
- prefix, (data & 0x40) ? 1 : 0,data & 0x3F);
- pos++;
- }
-@@ -710,7 +1311,7 @@
- /* Look for octet 6; this is identified by bits 5,6 == 10 */
- if (pos < len &&
- (ie->data[pos] & 0x60) == 0x40) {
-- pri_message(pri, "%c User information layer 2: %s (%d)\n",
-+ pri_message(ctrl, "%c User information layer 2: %s (%d)\n",
- prefix, l22str(ie->data[pos] & 0x1f),
- ie->data[pos] & 0x1f);
- pos++;
-@@ -718,7 +1319,7 @@
-
- /* Look for octet 7; this is identified by bits 5,6 == 11 */
- if (pos < len && (ie->data[pos] & 0x60) == 0x60) {
-- pri_message(pri, "%c User information layer 3: %s (%d)\n",
-+ pri_message(ctrl, "%c User information layer 3: %s (%d)\n",
- prefix, l32str(ie->data[pos] & 0x1f),
- ie->data[pos] & 0x1f);
- pos++;
-@@ -730,18 +1331,18 @@
- proto = ((ie->data[pos] & 0xF) << 4 ) |
- (ie->data[pos+1] & 0xF);
-
-- pri_message(pri, "%c Network layer: 0x%x\n", prefix,
-+ pri_message(ctrl, "%c Network layer: 0x%x\n", prefix,
- proto );
- pos += 2;
- }
- }
- }
-
--static FUNC_RECV(receive_bearer_capability)
-+static int receive_bearer_capability(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int pos=2;
- if (ie->data[0] & 0x60) {
-- pri_error(pri, "!! non-standard Q.931 standard field\n");
-+ pri_error(ctrl, "!! non-standard Q.931 standard field\n");
- return -1;
- }
- call->transcapability = ie->data[0] & 0x1f;
-@@ -788,7 +1389,7 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_bearer_capability)
-+static int transmit_bearer_capability(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- int tc;
- int pos;
-@@ -797,20 +1398,20 @@
- if(order > 1)
- return 0;
-
-- tc = call->transcapability;
-- if (pri->subchannel && !pri->bri) {
-+ if (ctrl->subchannel && !ctrl->bri) {
- /* Bearer capability is *hard coded* in GR-303 */
- ie->data[0] = 0x88;
- ie->data[1] = 0x90;
- return 4;
- }
--
-- if (call->justsignalling) {
-+
-+ if (call->cis_call) {
- ie->data[0] = 0xa8;
- ie->data[1] = 0x80;
- return 4;
- }
--
-+
-+ tc = call->transcapability;
- ie->data[0] = 0x80 | tc;
- ie->data[1] = call->transmoderate | 0x80;
-
-@@ -820,7 +1421,7 @@
- ie->data[pos++] = call->transmultiple | 0x80;
- }
-
-- if ((tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
-+ if ((tc & PRI_TRANS_CAP_DIGITAL) && (ctrl->switchtype == PRI_SWITCH_EUROISDN_E1) &&
- (call->transmoderate == TRANS_MODE_PACKET)) {
- /* Apparently EuroISDN switches don't seem to like user layer 2/3 */
- return 4;
-@@ -833,7 +1434,7 @@
-
- if (call->transmoderate != TRANS_MODE_PACKET) {
- /* If you have an AT&T 4ESS, you don't send any more info */
-- if ((pri->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
-+ if ((ctrl->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
- ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
- if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
- ie->data[pos++] = call->rateadaption | 0x80;
-@@ -908,6 +1509,30 @@
- return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
- }
-
-+/* Calling Party Category (Definitions from Q.763) */
-+static char *cpc2str(int plan)
-+{
-+ static struct msgtype plans[] = {
-+ { 0, "Unknown Source" },
-+ { 1, "Operator French" },
-+ { 2, "Operator English" },
-+ { 3, "Operator German" },
-+ { 4, "Operator Russian" },
-+ { 5, "Operator Spanish" },
-+ { 6, "Mut Agree Chinese" },
-+ { 7, "Mut Agreement" },
-+ { 8, "Mut Agree Japanese" },
-+ { 9, "National Operator" },
-+ { 10, "Ordinary Toll Caller" },
-+ { 11, "Priority Toll Caller" },
-+ { 12, "Data Call" },
-+ { 13, "Test Call" },
-+ { 14, "Spare" },
-+ { 15, "Pay Phone" },
-+ };
-+ return code2str(plan, plans, ARRAY_LEN(plans));
-+}
-+
- char *pri_pres2str(int pres)
- {
- static struct msgtype press[] = {
-@@ -934,51 +1559,134 @@
- num[len] = 0;
- }
-
--static FUNC_DUMP(dump_called_party_number)
-+static void q931_get_subaddr_specific(unsigned char *num, int maxlen, unsigned char *src, int len, char oddflag)
- {
-- unsigned char cnum[256];
-+ /* User Specified */
-+ int x;
-+ char *ptr = (char *) num;
-
-- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-- pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
-- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+ if (len <= 0) {
-+ num[0] = '\0';
-+ return;
-+ }
-+
-+ if (((len * 2) + 1) > maxlen) {
-+ len = (maxlen / 2) - 1;
-+ }
-+
-+ for (x = 0; x < (len - 1); ++x) {
-+ ptr += sprintf(ptr, "%02x", src[x]);
-+ }
-+
-+ if (oddflag) {
-+ /* ODD */
-+ sprintf(ptr, "%01x", (src[len - 1]) >> 4);
-+ } else {
-+ /* EVEN */
-+ sprintf(ptr, "%02x", src[len - 1]);
-+ }
- }
-
--static FUNC_DUMP(dump_called_party_subaddr)
-+static int transmit_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len, int order)
- {
-+ size_t datalen;
-+
-+ if (!q931_subaddress->valid) {
-+ return 0;
-+ }
-+
-+ datalen = q931_subaddress->length;
-+ if (!q931_subaddress->type) {
-+ /* 0 = NSAP */
-+ /* 0 = Odd/Even indicator */
-+ ie->data[0] = 0x80;
-+ } else {
-+ /* 2 = User Specified */
-+ ie->data[0] = q931_subaddress->odd_even_indicator ? 0xA8 : 0xA0;
-+ }
-+ memcpy(ie->data + offset, q931_subaddress->data, datalen);
-+
-+ return datalen + (offset + 2);
-+}
-+
-+static int receive_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len)
-+{
-+ if (len <= 0) {
-+ return -1;
-+ }
-+
-+ q931_subaddress->valid = 1;
-+ q931_subaddress->length = len;
-+ /* type: 0 = NSAP, 2 = User Specified */
-+ q931_subaddress->type = ((ie->data[0] & 0x70) >> 4);
-+ q931_subaddress->odd_even_indicator = (ie->data[0] & 0x08) ? 1 : 0;
-+ q931_get_number(q931_subaddress->data, sizeof(q931_subaddress->data),
-+ ie->data + offset, len);
-+
-+ return 0;
-+}
-+
-+static void dump_subaddr_helper(int full_ie, struct pri *ctrl, q931_ie *ie, int offset, int len, int datalen, char prefix, const char *named)
-+{
- unsigned char cnum[256];
-- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-- pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-- prefix, len, ie->data[0] >> 7,
-+
-+ if (!(ie->data[0] & 0x70)) {
-+ /* NSAP */
-+ q931_get_number(cnum, sizeof(cnum), ie->data + offset, datalen);
-+ } else {
-+ /* User Specified */
-+ q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset, datalen,
-+ ie->data[0] & 0x08);
-+ }
-+
-+ pri_message(ctrl,
-+ "%c %s Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-+ prefix, named, len, ie->data[0] >> 7,
- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- (ie->data[0] & 0x08) >> 3, cnum);
- }
-
--static FUNC_DUMP(dump_calling_party_number)
-+static void dump_called_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- unsigned char cnum[256];
-+
-+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+ pri_message(ctrl, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
-+ prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+}
-+
-+static void dump_called_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Called");
-+}
-+
-+static void dump_calling_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ unsigned char cnum[256];
- if (ie->data[0] & 0x80)
- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
- else
- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-- pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+ pri_message(ctrl, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- if (ie->data[0] & 0x80)
-- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
-+ pri_message(ctrl, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
- else
-- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+ pri_message(ctrl, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
- }
-
--static FUNC_DUMP(dump_calling_party_subaddr)
-+static void dump_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- unsigned char cnum[256];
-- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-- pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-- prefix, len, ie->data[0] >> 7,
-- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
-- (ie->data[0] & 0x08) >> 3, cnum);
-+ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Calling");
- }
-
--static FUNC_DUMP(dump_redirecting_number)
-+static void dump_calling_party_category(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-+ pri_message(ctrl, "%c Calling Party Category (len=%2d) [ Ext: %d Cat: %s (%d) ]\n",
-+ prefix, len, ie->data[0] >> 7, cpc2str(ie->data[0] & 0x0F), ie->data[0] & 0x0F);
-+}
-+
-+static void dump_redirecting_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
- unsigned char cnum[256];
- int i = 0;
- /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-@@ -986,172 +1694,369 @@
- do {
- switch(i) {
- case 0: /* Octet 3 */
-- pri_message(pri, "%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
-+ pri_message(ctrl, "%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- break;
- case 1: /* Octet 3a */
-- pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
-+ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
- prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
- break;
- case 2: /* Octet 3b */
-- pri_message(pri, "\n%c Ext: %d Reason: %s (%d)",
-+ pri_message(ctrl, "\n%c Ext: %d Reason: %s (%d)",
- 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);
-+ pri_message(ctrl, " '%s' ]\n", cnum);
- }
-
--static FUNC_DUMP(dump_connected_number)
-+static void dump_redirection_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- unsigned char cnum[256];
- int i = 0;
- /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
- walking through all bytes until one with ext bit (8) set to 1 */
- do {
-+ switch (i) {
-+ case 0: /* Octet 3 */
-+ pri_message(ctrl,
-+ "%c Redirection Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
-+ prefix, len, ie->data[0] >> 7,
-+ ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07,
-+ npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+ break;
-+ case 1: /* Octet 3a */
-+ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
-+ prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-+ pri_message(ctrl, " '%s' ]\n", cnum);
-+}
-+
-+static int receive_connected_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ int i = 0;
-+
-+ call->connected_number_in_message = 1;
-+ call->remote_id.number.valid = 1;
-+ call->remote_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
-+ switch (i) {
-+ case 0:
-+ call->remote_id.number.plan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ /* Keep only the presentation and screening fields */
-+ call->remote_id.number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->remote_id.number.str, sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
-+
-+ return 0;
-+}
-+
-+static int transmit_connected_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ size_t datalen;
-+
-+ if (!call->local_id.number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->local_id.number.str);
-+ ie->data[0] = call->local_id.number.plan;
-+ ie->data[1] = 0x80 | call->local_id.number.presentation;
-+ memcpy(ie->data + 2, call->local_id.number.str, datalen);
-+ return datalen + (2 + 2);
-+}
-+
-+static void dump_connected_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ unsigned char cnum[256];
-+ int i = 0;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
- switch(i) {
- case 0: /* Octet 3 */
-- pri_message(pri, "%c Connected Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
-+ pri_message(ctrl, "%c Connected Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- break;
- case 1: /* Octet 3a */
-- pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
-+ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
- 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);
-+ pri_message(ctrl, " '%s' ]\n", cnum);
- }
-
-+static int receive_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ if (len < 3) {
-+ return -1;
-+ }
-
--static FUNC_RECV(receive_redirecting_number)
-+ return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie,
-+ 1, len - 3);
-+}
-+
-+static int transmit_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-+ return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie,
-+ 1, len, order);
-+}
-+
-+static void dump_connected_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Connected");
-+}
-+
-+static int receive_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
- int i = 0;
-
-+ call->redirecting_number_in_message = 1;
-+ call->redirecting.from.number.valid = 1;
-+ call->redirecting.from.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ call->redirecting.reason = PRI_REDIR_UNKNOWN;
- /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
- walking through all bytes until one with ext bit (8) set to 1 */
- do {
-- switch(i) {
-+ switch (i) {
- case 0:
-- call->redirectingplan = ie->data[i] & 0x7f;
-+ call->redirecting.from.number.plan = ie->data[i] & 0x7f;
- break;
- case 1:
-- call->redirectingpres = ie->data[i] & 0x7f;
-+ /* Keep only the presentation and screening fields */
-+ call->redirecting.from.number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
- break;
- case 2:
-- call->redirectingreason = ie->data[i] & 0x0f;
-+ call->redirecting.reason = ie->data[i] & 0x0f;
- break;
- }
-- }
-- while(!(ie->data[i++] & 0x80));
-- q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->redirecting.from.number.str, sizeof(call->redirecting.from.number.str), ie->data + i, ie->len - i);
- return 0;
- }
-
--static FUNC_SEND(transmit_redirecting_number)
-+static int transmit_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-+ size_t datalen;
-+
- if (order > 1)
- return 0;
-- if (call->redirectingnum && *call->redirectingnum) {
-- ie->data[0] = call->redirectingplan;
-- ie->data[1] = call->redirectingpres;
-- ie->data[2] = (call->redirectingreason & 0x0f) | 0x80;
-- memcpy(ie->data + 3, call->redirectingnum, strlen(call->redirectingnum));
-- return strlen(call->redirectingnum) + 3 + 2;
-+ if (!call->redirecting.from.number.valid) {
-+ return 0;
- }
-- return 0;
-+
-+ datalen = strlen(call->redirecting.from.number.str);
-+ ie->data[0] = call->redirecting.from.number.plan;
-+#if 1
-+ /* ETSI and Q.952 do not define the screening field */
-+ ie->data[1] = call->redirecting.from.number.presentation & PRI_PRES_RESTRICTION;
-+#else
-+ /* Q.931 defines the screening field */
-+ ie->data[1] = call->redirecting.from.number.presentation;
-+#endif
-+ ie->data[2] = (call->redirecting.reason & 0x0f) | 0x80;
-+ memcpy(ie->data + 3, call->redirecting.from.number.str, datalen);
-+ return datalen + (3 + 2);
- }
-
--static FUNC_DUMP(dump_redirecting_subaddr)
-+static void dump_redirecting_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- unsigned char cnum[256];
-- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-- pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-- prefix, len, ie->data[0] >> 7,
-- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
-- (ie->data[0] & 0x08) >> 3, cnum);
-+ dump_subaddr_helper(full_ie, ctrl, ie, 2, len, len - 4, prefix, "Redirecting");
- }
-
--static FUNC_RECV(receive_calling_party_subaddr)
-+static int receive_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-- /* copy digits to call->callingsubaddr */
-- q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3);
-+ int i = 0;
-+
-+ call->redirection_number.valid = 1;
-+ call->redirection_number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
-+ switch (i) {
-+ case 0:
-+ call->redirection_number.plan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ /* Keep only the presentation and screening fields */
-+ call->redirection_number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->redirection_number.str, sizeof(call->redirection_number.str), ie->data + i, ie->len - i);
- return 0;
- }
-
--static FUNC_RECV(receive_called_party_number)
-+static int transmit_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- /* copy digits to call->callednum */
-- q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
-- call->calledplan = ie->data[0] & 0x7f;
-- return 0;
-+ size_t datalen;
-+
-+ if (order > 1) {
-+ return 0;
-+ }
-+ if (!call->redirection_number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->redirection_number.str);
-+ ie->data[0] = call->redirection_number.plan;
-+ ie->data[1] = (call->redirection_number.presentation & PRI_PRES_RESTRICTION) | 0x80;
-+ memcpy(ie->data + 2, call->redirection_number.str, datalen);
-+ return datalen + (2 + 2);
- }
-
--static FUNC_SEND(transmit_called_party_number)
-+static int receive_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-- ie->data[0] = 0x80 | call->calledplan;
-- if (*call->callednum)
-- memcpy(ie->data + 1, call->callednum, strlen(call->callednum));
-- return strlen(call->callednum) + 3;
-+ if (len < 3) {
-+ return -1;
-+ }
-+
-+ return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie,
-+ 1, len - 3);
- }
-
--static FUNC_RECV(receive_calling_party_number)
-+static int transmit_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- u_int8_t *data;
-- size_t length;
--
-- if (ie->data[0] & 0x80) {
-- data = ie->data + 1;
-- length = len - 3;
-- call->callerpres = 0; /* PI presentation allowed SI user-provided, not screened */
-- } else {
-- data = ie->data + 2;
-- length = len - 4;
-- call->callerpres = ie->data[1] & 0x7f;
-+ return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie,
-+ 1, len, order);
-+}
-+
-+static int receive_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ if (len < 3) {
-+ return -1;
- }
-+ return receive_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie, 1,
-+ len - 3);
-+}
-
-- if (call->callerpres == PRES_ALLOWED_NETWORK_NUMBER ||
-- call->callerpres == PRES_PROHIB_NETWORK_NUMBER) {
-- q931_get_number((u_int8_t *)call->callerani, sizeof(call->callerani), data, length);
-- call->callerplanani = ie->data[0] & 0x7f;
-+static int transmit_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ return transmit_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie,
-+ 1, len, order);
-+}
-
-- if (!*call->callernum) { /*Copy ANI to CallerID if CallerID is not already set */
-- libpri_copy_string(call->callernum, call->callerani, sizeof(call->callernum));
-- call->callerplan = call->callerplanani;
-+static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ size_t called_len;
-+ size_t max_len;
-+ char *called_end;
-+
-+ if (len < 3) {
-+ return -1;
-+ }
-+
-+ call->called.number.valid = 1;
-+ call->called.number.plan = ie->data[0] & 0x7f;
-+ if (msgtype == Q931_SETUP) {
-+ q931_get_number((unsigned char *) call->called.number.str,
-+ sizeof(call->called.number.str), ie->data + 1, len - 3);
-+ } else if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) {
-+ /*
-+ * Since we are receiving overlap digits now, we need to append
-+ * them to any previously received digits in call->called.number.str.
-+ */
-+ called_len = strlen(call->called.number.str);
-+ called_end = call->called.number.str + called_len;
-+ max_len = (sizeof(call->called.number.str) - 1) - called_len;
-+ if (max_len < len - 3) {
-+ called_len = max_len;
-+ } else {
-+ called_len = len - 3;
- }
--
-- } else {
-- q931_get_number((u_int8_t *)call->callernum, sizeof(call->callernum), data, length);
-- call->callerplan = ie->data[0] & 0x7f;
-+ strncat(called_end, (char *) ie->data + 1, called_len);
- }
-
-+ q931_get_number((unsigned char *) call->overlap_digits, sizeof(call->overlap_digits),
-+ ie->data + 1, len - 3);
- return 0;
- }
-
--static FUNC_SEND(transmit_calling_party_number)
-+static int transmit_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- ie->data[0] = call->callerplan;
-- ie->data[1] = 0x80 | call->callerpres;
-- if (*call->callernum)
-- memcpy(ie->data + 2, call->callernum, strlen(call->callernum));
-- return strlen(call->callernum) + 4;
-+ size_t datalen;
-+
-+ if (!call->called.number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->overlap_digits);
-+ ie->data[0] = 0x80 | call->called.number.plan;
-+ memcpy(ie->data + 1, call->overlap_digits, datalen);
-+ return datalen + (1 + 2);
- }
-
--static FUNC_DUMP(dump_user_user)
-+static int receive_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-+ int i = 0;
-+
-+ call->remote_id.number.valid = 1;
-+ call->remote_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
-+ switch (i) {
-+ case 0:
-+ call->remote_id.number.plan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ /* Keep only the presentation and screening fields */
-+ call->remote_id.number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->remote_id.number.str,
-+ sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
-+
-+ return 0;
-+}
-+
-+static int transmit_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ size_t datalen;
-+
-+ if (!call->local_id.number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->local_id.number.str);
-+ ie->data[0] = call->local_id.number.plan;
-+ ie->data[1] = 0x80 | call->local_id.number.presentation;
-+ memcpy(ie->data + 2, call->local_id.number.str, datalen);
-+ return datalen + (2 + 2);
-+}
-+
-+static void dump_user_user(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
- int x;
-- pri_message(pri, "%c User-User Information (len=%2d) [", prefix, len);
-+ pri_message(ctrl, "%c User-User Information (len=%2d) [", prefix, len);
- for (x=0;x<ie->len;x++)
-- pri_message(pri, " %02x", ie->data[x] & 0x7f);
-- pri_message(pri, " ]\n");
-+ pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
-+ pri_message(ctrl, " ]\n");
- }
-
-
--static FUNC_RECV(receive_user_user)
-+static int receive_user_user(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->useruserprotocoldisc = ie->data[0] & 0xff;
- if (call->useruserprotocoldisc == 4) /* IA5 */
-@@ -1159,7 +2064,7 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_user_user)
-+static int transmit_user_user(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- int datalen = strlen(call->useruserinfo);
- if (datalen > 0) {
-@@ -1180,6 +2085,29 @@
- return 0;
- }
-
-+static void dump_change_status(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ int x;
-+
-+ pri_message(ctrl, "%c Change Status Information (len=%2d) [", prefix, len);
-+ for (x=0; x<ie->len; x++) {
-+ pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
-+ }
-+ pri_message(ctrl, " ]\n");
-+}
-+
-+static int receive_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ call->changestatus = ie->data[0] & 0x0f;
-+ return 0;
-+}
-+
-+static int transmit_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ ie->data[0] = 0xc0 | call->changestatus;
-+ return 3;
-+}
-+
- static char *prog2str(int prog)
- {
- static struct msgtype progs[] = {
-@@ -1222,47 +2150,83 @@
- return code2str(loc, locs, sizeof(locs) / sizeof(locs[0]));
- }
-
--static FUNC_DUMP(dump_progress_indicator)
-+static void dump_progress_indicator(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
-+ pri_message(ctrl, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
- prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
- (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
-- pri_message(pri, "%c Ext: %d Progress Description: %s (%d) ]\n",
-+ pri_message(ctrl, "%c Ext: %d Progress Description: %s (%d) ]\n",
- prefix, ie->data[1] >> 7, prog2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
- }
-
--static FUNC_RECV(receive_display)
-+static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- unsigned char *data;
-+
-+ switch (msgtype) {
-+ case Q931_SETUP:
-+ case Q931_CONNECT:
-+ /*
-+ * Only keep the display message on SETUP and CONNECT messages
-+ * as the remote name.
-+ */
-+ break;
-+ default:
-+ return 0;
-+ }
-+
-+ call->remote_id.name.valid = 1;
-+
- data = ie->data;
- if (data[0] & 0x80) {
- /* Skip over character set */
- data++;
- len--;
- }
-- q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+ call->remote_id.name.char_set = PRI_CHAR_SET_ISO8859_1;
-+
-+ q931_get_number((unsigned char *) call->remote_id.name.str, sizeof(call->remote_id.name.str), data, len - 2);
-+ if (call->remote_id.name.str[0]) {
-+ call->remote_id.name.presentation = PRI_PRES_ALLOWED;
-+ } else {
-+ call->remote_id.name.presentation = PRI_PRES_RESTRICTED;
-+ }
- return 0;
- }
-
--static FUNC_SEND(transmit_display)
-+static int transmit_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-+ size_t datalen;
- int i;
--
-- if ((pri->switchtype == PRI_SWITCH_QSIG) ||
-- ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) && (pri->localtype == PRI_CPE)) ||
-- !call->callername[0])
-- return 0;
-
- i = 0;
-- if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
-+
-+ if (!call->local_id.name.valid || !call->local_id.name.str[0]) {
-+ return 0;
-+ }
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ /* Q.SIG supports names */
-+ return 0;
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (ctrl->localtype == PRI_CPE) {
-+ return 0;
-+ }
-+ break;
-+ default:
-+ /* Prefix name with character set indicator. */
- ie->data[0] = 0xb1;
- ++i;
-+ break;
- }
-- memcpy(ie->data + i, call->callername, strlen(call->callername));
-- return 2 + i + strlen(call->callername);
-+
-+ datalen = strlen(call->local_id.name.str);
-+ memcpy(ie->data + i, call->local_id.name.str, datalen);
-+ return 2 + i + datalen;
- }
-
--static FUNC_RECV(receive_progress_indicator)
-+static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->progloc = ie->data[0] & 0xf;
- call->progcode = (ie->data[0] & 0x60) >> 5;
-@@ -1298,153 +2262,204 @@
- call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
- break;
- default:
-- pri_error(pri, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
-+ pri_error(ctrl, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
- break;
- }
- return 0;
- }
-
--static FUNC_SEND(transmit_facility)
-+static void q931_apdu_timeout(void *data);
-+
-+static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- struct apdu_event *tmp;
-- int i = 0;
-+ struct apdu_event **prev;
-+ struct apdu_event *cur;
-+ int apdu_len;
-
-- for (tmp = call->apdus; tmp; tmp = tmp->next) {
-- if ((tmp->message == msgtype) && !tmp->sent)
-+ for (prev = &call->apdus, cur = call->apdus;
-+ cur;
-+ prev = &cur->next, cur = cur->next) {
-+ if (!cur->sent && cur->message == msgtype) {
- break;
-+ }
- }
--
-- if (!tmp) /* No APDU found */
-+ if (!cur) {
-+ /* No APDU found */
- return 0;
-+ }
-
-- 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);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "Adding facility ie contents to send in %s message:\n",
-+ msg2str(msgtype));
-+ facility_decode_dump(ctrl, cur->apdu, cur->apdu_len);
-+ }
-+
-+ if (len < cur->apdu_len) {
-+ pri_error(ctrl,
-+ "Could not fit facility ie in message. Size needed:%d Available space:%d\n",
-+ cur->apdu_len + 2, len);
-+
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+
-+ if (cur->response.callback) {
-+ /* Indicate to callback that the APDU had a problem getting sent. */
-+ cur->response.callback(APDU_CALLBACK_REASON_ERROR, ctrl, call, cur, NULL);
-+ }
-+
-+ free(cur);
- return 0;
- }
--
-- memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
-- i += tmp->apdu_len;
-- tmp->sent = 1;
-
-- return i + 2;
-+ memcpy(ie->data, cur->apdu, cur->apdu_len);
-+ apdu_len = cur->apdu_len;
-+ cur->sent = 1;
-+
-+ if (cur->response.callback && cur->response.timeout_time) {
-+ int duration;
-+
-+ if (0 < cur->response.timeout_time) {
-+ /* Sender specified timeout duration. */
-+ duration = cur->response.timeout_time;
-+ } else {
-+ /* Sender wants to use the typical timeout duration. */
-+ duration = ctrl->timers[PRI_TIMER_T_RESPONSE];
-+ }
-+ cur->timer = pri_schedule_event(ctrl, duration, q931_apdu_timeout, cur);
-+ if (!cur->timer) {
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+
-+ /* Indicate to callback that the APDU had a problem getting sent. */
-+ cur->response.callback(APDU_CALLBACK_REASON_ERROR, ctrl, call, cur, NULL);
-+
-+ free(cur);
-+ }
-+ } else if (!cur->timer) {
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+ free(cur);
-+ }
-+
-+ return apdu_len + 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;
--
-- if (ie->len < 1)
-+ /* Delay processing facility ie's till after all other ie's are processed. */
-+ if (MAX_FACILITY_IES <= ctrl->facility.count) {
-+ pri_message(ctrl, "!! Too many facility ie's to delay.\n");
- return -1;
-+ }
-+ /* Make sure we have enough room for the protocol profile ie octet(s) */
-+ if (ie->data + ie->len < ie->data + 2) {
-+ return -1;
-+ }
-
-- 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);
-+ /* Save the facility ie location for delayed decode. */
-+ ctrl->facility.ie[ctrl->facility.count] = ie;
-+ ctrl->facility.codeset[ctrl->facility.count] = Q931_IE_CODESET((unsigned) full_ie);
-+ ++ctrl->facility.count;
-+ return 0;
-+}
-+
-+static int process_facility(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie)
-+{
-+ struct fac_extension_header header;
-+ struct rose_message rose;
-+ const unsigned char *pos;
-+ const unsigned char *end;
-+
-+ pos = ie->data;
-+ end = ie->data + ie->len;
-+
-+ /* Make sure we have enough room for the protocol profile ie octet(s) */
-+ if (end < pos + 2) {
- return -1;
-+ }
-+ switch (*pos & Q932_PROTOCOL_MASK) {
-+ case Q932_PROTOCOL_ROSE:
- case Q932_PROTOCOL_EXTENSIONS:
-- state = Q932_STATE_NFE;
-- next_protocol = Q932_PROTOCOL_ROSE;
- break;
-- case Q932_PROTOCOL_ROSE:
-- break;
- default:
-- pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol);
-+ 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);
-+ }
- return -1;
- }
-- /* Service indicator octet - Just ignore for now */
-- if (!(ie->data[i] & 0x80))
-- i++;
-- i++;
-+ if (!(*pos & 0x80)) {
-+ /* DMS-100 Service indicator octet - Just ignore for now */
-+ ++pos;
-+ }
-+ ++pos;
-
-- if (ie->len < 3)
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ asn1_dump(ctrl, pos, end);
-+ }
-+
-+ pos = fac_dec_extension_header(ctrl, pos, end, &header);
-+ if (!pos) {
- 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;
-- }
-+ }
-+ 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);
- }
-- i += (comp->len + 2);
-+ return -1;
- }
--#undef Q932_HANDLE
-
-+ pos = rose_decode(ctrl, pos, end, &rose);
-+ if (!pos) {
-+ return -1;
-+ }
-+ switch (rose.type) {
-+ case ROSE_COMP_TYPE_INVOKE:
-+ rose_handle_invoke(ctrl, call, msgtype, ie, &header, &rose.component.invoke);
-+ break;
-+ case ROSE_COMP_TYPE_RESULT:
-+ rose_handle_result(ctrl, call, msgtype, ie, &header, &rose.component.result);
-+ break;
-+ case ROSE_COMP_TYPE_ERROR:
-+ rose_handle_error(ctrl, call, msgtype, ie, &header, &rose.component.error);
-+ break;
-+ case ROSE_COMP_TYPE_REJECT:
-+ rose_handle_reject(ctrl, call, msgtype, ie, &header, &rose.component.reject);
-+ break;
-+ default:
-+ return -1;
-+ }
- return 0;
- }
-
--static FUNC_SEND(transmit_progress_indicator)
-+static void q931_handle_facilities(struct pri *ctrl, q931_call *call, int msgtype)
- {
-+ unsigned idx;
-+ unsigned codeset;
-+ unsigned full_ie;
-+ q931_ie *ie;
-+
-+ for (idx = 0; idx < ctrl->facility.count; ++idx) {
-+ ie = ctrl->facility.ie[idx];
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ codeset = ctrl->facility.codeset[idx];
-+ full_ie = Q931_FULL_IE(codeset, ie->ie);
-+ pri_message(ctrl, "-- Delayed processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
-+ }
-+ process_facility(ctrl, call, msgtype, ie);
-+ }
-+}
-+
-+static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
- int code, mask;
- /* Can't send progress indicator on GR-303 -- EVER! */
-- if (pri->subchannel && !pri->bri)
-+ if (ctrl->subchannel && !ctrl->bri)
- return 0;
- if (call->progressmask > 0) {
- if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN))
-@@ -1467,7 +2482,7 @@
- code = Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
- else {
- code = 0;
-- pri_error(pri, "XXX Undefined progress bit: %x\n", call->progressmask);
-+ pri_error(ctrl, "XXX Undefined progress bit: %x\n", call->progressmask);
- }
- if (code) {
- ie->data[0] = 0x80 | (call->progcode << 5) | (call->progloc);
-@@ -1479,82 +2494,139 @@
- /* Leave off */
- return 0;
- }
--static FUNC_SEND(transmit_call_state)
-+static int transmit_call_state(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- if (call->ourcallstate > -1 ) {
-+ ie->data[0] = Q931_CALL_STATE_NULL;
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_NULL:
-+ case Q931_CALL_STATE_CALL_INITIATED:
-+ case Q931_CALL_STATE_OVERLAP_SENDING:
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_CALL_PRESENT:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_ACTIVE:
-+ case Q931_CALL_STATE_DISCONNECT_REQUEST:
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_SUSPEND_REQUEST:
-+ case Q931_CALL_STATE_RESUME_REQUEST:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ case Q931_CALL_STATE_CALL_ABORT:
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ case Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE:
-+ case Q931_CALL_STATE_RESTART_REQUEST:
-+ case Q931_CALL_STATE_RESTART:
- ie->data[0] = call->ourcallstate;
-- return 3;
-+ break;
-+ case Q931_CALL_STATE_NOT_SET:
-+ break;
- }
-- return 0;
-+ return 3;
- }
-
--static FUNC_RECV(receive_call_state)
-+static int receive_call_state(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->sugcallstate = ie->data[0] & 0x3f;
- return 0;
- }
-
--static char *callstate2str(int callstate)
-+/*!
-+ * \brief Convert the internal Q.931 call state to a string.
-+ *
-+ * \param callstate Internal Q.931 call state.
-+ *
-+ * \return String equivalent of the given Q.931 call state.
-+ */
-+const char *q931_call_state_str(enum Q931_CALL_STATE callstate)
- {
- static struct msgtype callstates[] = {
-- { 0, "Null" },
-- { 1, "Call Initiated" },
-- { 2, "Overlap sending" },
-- { 3, "Outgoing call Proceeding" },
-- { 4, "Call Delivered" },
-- { 6, "Call Present" },
-- { 7, "Call Received" },
-- { 8, "Connect Request" },
-- { 9, "Incoming Call Proceeding" },
-- { 10, "Active" },
-- { 11, "Disconnect Request" },
-- { 12, "Disconnect Indication" },
-- { 15, "Suspend Request" },
-- { 17, "Resume Request" },
-- { 19, "Release Request" },
-- { 22, "Call Abort" },
-- { 25, "Overlap Receiving" },
-- { 61, "Restart Request" },
-- { 62, "Restart" },
-+/* *INDENT-OFF* */
-+ { Q931_CALL_STATE_NULL, "Null" },
-+ { Q931_CALL_STATE_CALL_INITIATED, "Call Initiated" },
-+ { Q931_CALL_STATE_OVERLAP_SENDING, "Overlap Sending" },
-+ { Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING, "Outgoing Call Proceeding" },
-+ { Q931_CALL_STATE_CALL_DELIVERED, "Call Delivered" },
-+ { Q931_CALL_STATE_CALL_PRESENT, "Call Present" },
-+ { Q931_CALL_STATE_CALL_RECEIVED, "Call Received" },
-+ { Q931_CALL_STATE_CONNECT_REQUEST, "Connect Request" },
-+ { Q931_CALL_STATE_INCOMING_CALL_PROCEEDING, "Incoming Call Proceeding" },
-+ { Q931_CALL_STATE_ACTIVE, "Active" },
-+ { Q931_CALL_STATE_DISCONNECT_REQUEST, "Disconnect Request" },
-+ { Q931_CALL_STATE_DISCONNECT_INDICATION, "Disconnect Indication" },
-+ { Q931_CALL_STATE_SUSPEND_REQUEST, "Suspend Request" },
-+ { Q931_CALL_STATE_RESUME_REQUEST, "Resume Request" },
-+ { Q931_CALL_STATE_RELEASE_REQUEST, "Release Request" },
-+ { Q931_CALL_STATE_CALL_ABORT, "Call Abort" },
-+ { Q931_CALL_STATE_OVERLAP_RECEIVING, "Overlap Receiving" },
-+ { Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE, "Call Independent Service" },
-+ { Q931_CALL_STATE_RESTART_REQUEST, "Restart Request" },
-+ { Q931_CALL_STATE_RESTART, "Restart" },
-+ { Q931_CALL_STATE_NOT_SET, "Not set. Internal use only." },
-+/* *INDENT-ON* */
- };
-- return code2str(callstate, callstates, sizeof(callstates) / sizeof(callstates[0]));
-+ return code2str(callstate, callstates, ARRAY_LEN(callstates));
- }
-
--static FUNC_DUMP(dump_call_state)
-+/*!
-+ * \internal
-+ * \brief Convert the Q.932 supplementary hold state to a string.
-+ *
-+ * \param state Q.932 supplementary hold state.
-+ *
-+ * \return String equivalent of the given hold state.
-+ */
-+static const char *q931_hold_state_str(enum Q931_HOLD_STATE state)
- {
-- pri_message(pri, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
-+ static struct msgtype hold_states[] = {
-+/* *INDENT-OFF* */
-+ { Q931_HOLD_STATE_IDLE, "Idle" },
-+ { Q931_HOLD_STATE_HOLD_REQ, "Hold Request" },
-+ { Q931_HOLD_STATE_HOLD_IND, "Hold Indication" },
-+ { Q931_HOLD_STATE_CALL_HELD, "Call Held" },
-+ { Q931_HOLD_STATE_RETRIEVE_REQ, "Retrieve Request" },
-+ { Q931_HOLD_STATE_RETRIEVE_IND, "Retrieve Indication" },
-+/* *INDENT-ON* */
-+ };
-+ return code2str(state, hold_states, ARRAY_LEN(hold_states));
-+}
-+
-+static void dump_call_state(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ pri_message(ctrl, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
- prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0xC0) >> 6), (ie->data[0] & 0xC0) >> 6,
-- callstate2str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
-+ q931_call_state_str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
- }
-
--static FUNC_DUMP(dump_call_identity)
-+static void dump_call_identity(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int x;
-- pri_message(pri, "%c Call Identity (len=%2d) [ ", prefix, len);
-+ pri_message(ctrl, "%c Call Identity (len=%2d) [ ", prefix, len);
- for (x=0;x<ie->len;x++)
-- pri_message(pri, "0x%02X ", ie->data[x]);
-- pri_message(pri, " ]\n");
-+ pri_message(ctrl, "0x%02X ", ie->data[x]);
-+ pri_message(ctrl, " ]\n");
- }
-
--static FUNC_DUMP(dump_time_date)
-+static void dump_time_date(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len);
-+ pri_message(ctrl, "%c Time Date (len=%2d) [ ", prefix, len);
- if (ie->len > 0)
-- pri_message(pri, "%02d", ie->data[0]);
-+ pri_message(ctrl, "%02d", ie->data[0]);
- if (ie->len > 1)
-- pri_message(pri, "-%02d", ie->data[1]);
-+ pri_message(ctrl, "-%02d", ie->data[1]);
- if (ie->len > 2)
-- pri_message(pri, "-%02d", ie->data[2]);
-+ pri_message(ctrl, "-%02d", ie->data[2]);
- if (ie->len > 3)
-- pri_message(pri, " %02d", ie->data[3]);
-+ pri_message(ctrl, " %02d", ie->data[3]);
- if (ie->len > 4)
-- pri_message(pri, ":%02d", ie->data[4]);
-+ pri_message(ctrl, ":%02d", ie->data[4]);
- if (ie->len > 5)
-- pri_message(pri, ":%02d", ie->data[5]);
-- pri_message(pri, " ]\n");
-+ pri_message(ctrl, ":%02d", ie->data[5]);
-+ pri_message(ctrl, " ]\n");
- }
-
--static FUNC_DUMP(dump_keypad_facility)
-+static void dump_keypad_facility(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- char tmp[64];
-
-@@ -1563,10 +2635,10 @@
-
- memcpy(tmp, ie->data, ie->len);
- tmp[ie->len] = '\0';
-- pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
-+ pri_message(ctrl, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
- }
-
--static FUNC_RECV(receive_keypad_facility)
-+static int receive_keypad_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int mylen;
-
-@@ -1584,27 +2656,19 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_keypad_facility)
-+static int transmit_keypad_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- int sublen;
-
- sublen = strlen(call->keypad_digits);
--
-- if (sublen > 32) {
-- sublen = 32;
-- call->keypad_digits[32] = '\0';
-- }
--
- if (sublen) {
-- libpri_copy_string((char *)ie->data, (char *)call->keypad_digits, sizeof(call->keypad_digits));
-- /* Make sure we clear the field */
-- call->keypad_digits[0] = '\0';
-+ libpri_copy_string((char *) ie->data, call->keypad_digits, sizeof(call->keypad_digits));
- return sublen + 2;
- } else
- return 0;
- }
-
--static FUNC_DUMP(dump_display)
-+static void dump_display(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int x, y;
- char *buf = malloc(len + 1);
-@@ -1618,7 +2682,7 @@
- for (y=x; x<ie->len; x++)
- buf[x] = ie->data[x] & 0x7f;
- buf[x] = '\0';
-- pri_message(pri, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]);
-+ pri_message(ctrl, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]);
- free(buf);
- }
- }
-@@ -1626,10 +2690,10 @@
- #define CHECK_OVERFLOW(limit) \
- if (tmpptr - tmp + limit >= sizeof(tmp)) { \
- *tmpptr = '\0'; \
-- pri_message(pri, "%s", tmpptr = tmp); \
-+ pri_message(ctrl, "%s", tmpptr = tmp); \
- }
-
--static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
-+static void dump_ie_data(struct pri *ctrl, unsigned char *c, int len)
- {
- static char hexs[16] = "0123456789ABCDEF";
- char tmp[1024], *tmpptr;
-@@ -1665,47 +2729,54 @@
- if (lastascii)
- *tmpptr++ = '\'';
- *tmpptr = '\0';
-- pri_message(pri, "%s", tmp);
-+ pri_message(ctrl, "%s", tmp);
- }
-
--static FUNC_DUMP(dump_facility)
-+static void dump_facility(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- 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");
-+ pri_message(ctrl, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
-+ dump_ie_data(ctrl, ie->data, ie->len);
-+ pri_message(ctrl, " ]\n");
-+#if 0 /* Lets not dump parse of facility contents here anymore. */
-+ /*
-+ * The ASN.1 decode dump has already been done when the facility ie was added to the outgoing
-+ * message or the ASN.1 decode dump will be done when the facility ie is processed on incoming
-+ * messages. This dump is redundant and very noisy.
-+ */
- 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);
-+ int dataat = (ie->data[0] & 0x80) ? 1 : 2;
-+
-+ pri_message(ctrl, "PROTOCOL %02X\n", ie->data[0] & Q932_PROTOCOL_MASK);
-+ asn1_dump(ctrl, ie->data + dataat, ie->data + ie->len);
- }
--
-+#endif /* Lets not dump parse of facility contents here anymore. */
- }
-
--static FUNC_DUMP(dump_network_spec_fac)
-+static void dump_network_spec_fac(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
-+ pri_message(ctrl, "%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(ctrl, "%s", code2str(ie->data[1], facilities, ARRAY_LEN(facilities)));
- }
- else
-- dump_ie_data(pri, ie->data, ie->len);
-- pri_message(pri, " ]\n");
-+ dump_ie_data(ctrl, ie->data, ie->len);
-+ pri_message(ctrl, " ]\n");
- }
-
--static FUNC_RECV(receive_network_spec_fac)
-+static int receive_network_spec_fac(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- return 0;
- }
-
--static FUNC_SEND(transmit_network_spec_fac)
-+static int transmit_network_spec_fac(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- /* We are ready to transmit single IE only */
- if (order > 1)
- return 0;
-
-- if (pri->nsf != PRI_NSF_NONE) {
-+ if (ctrl->nsf != PRI_NSF_NONE) {
- ie->data[0] = 0x00;
-- ie->data[1] = pri->nsf;
-+ ie->data[1] = ctrl->nsf;
- return 4;
- }
- /* Leave off */
-@@ -1732,13 +2803,13 @@
- return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0]));
- }
-
--static FUNC_DUMP(dump_cause)
-+static void dump_cause(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int x;
-- pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
-+ pri_message(ctrl, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
- prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
- (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
-- pri_message(pri, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
-+ pri_message(ctrl, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
- prefix, (ie->data[1] >> 7), pri_cause2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f,
- pri_causeclass2str((ie->data[1] & 0x7f) >> 4), (ie->data[1] & 0x7f) >> 4);
- if (ie->len < 3)
-@@ -1747,29 +2818,29 @@
- switch(ie->data[1] & 0x7f) {
- case PRI_CAUSE_IE_NONEXIST:
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
-+ pri_message(ctrl, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
- break;
- case PRI_CAUSE_WRONG_CALL_STATE:
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
-+ pri_message(ctrl, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
- break;
- case PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
-- pri_message(pri, "%c Cause data:", prefix);
-+ pri_message(ctrl, "%c Cause data:", prefix);
- for (x=2;x<ie->len;x++)
-- pri_message(pri, " %02x", ie->data[x]);
-- pri_message(pri, " (Timer T");
-+ pri_message(ctrl, " %02x", ie->data[x]);
-+ pri_message(ctrl, " (Timer T");
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
-- pri_message(pri, ")\n");
-+ pri_message(ctrl, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
-+ pri_message(ctrl, ")\n");
- break;
- default:
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
-+ pri_message(ctrl, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
- break;
- }
- }
-
--static FUNC_RECV(receive_cause)
-+static int receive_cause(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->causeloc = ie->data[0] & 0xf;
- call->causecode = (ie->data[0] & 0x60) >> 5;
-@@ -1777,7 +2848,7 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_cause)
-+static int transmit_cause(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- /* We are ready to transmit single IE only */
- if (order > 1)
-@@ -1793,23 +2864,23 @@
- }
- }
-
--static FUNC_DUMP(dump_sending_complete)
-+static void dump_sending_complete(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Sending Complete (len=%2d)\n", prefix, len);
-+ pri_message(ctrl, "%c Sending Complete (len=%2d)\n", prefix, len);
- }
-
--static FUNC_RECV(receive_sending_complete)
-+static int receive_sending_complete(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- /* We've got a "Complete" message: Exect no further digits. */
- call->complete = 1;
- return 0;
- }
-
--static FUNC_SEND(transmit_sending_complete)
-+static int transmit_sending_complete(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- if ((pri->overlapdial && call->complete) || /* Explicit */
-- (!pri->overlapdial && ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) ||
-- /* Implicit */ (pri->switchtype == PRI_SWITCH_EUROISDN_T1)))) {
-+ if ((ctrl->overlapdial && call->complete) || /* Explicit */
-+ (!ctrl->overlapdial && ((ctrl->switchtype == PRI_SWITCH_EUROISDN_E1) ||
-+ /* Implicit */ (ctrl->switchtype == PRI_SWITCH_EUROISDN_T1)))) {
- /* Include this single-byte IE */
- return 1;
- }
-@@ -1846,18 +2917,18 @@
- return code2str(info, notifies, sizeof(notifies) / sizeof(notifies[0]));
- }
-
--static FUNC_DUMP(dump_notify)
-+static void dump_notify(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);
-+ pri_message(ctrl, "%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);
- }
-
--static FUNC_RECV(receive_notify)
-+static int receive_notify(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->notify = ie->data[0] & 0x7F;
- return 0;
- }
-
--static FUNC_SEND(transmit_notify)
-+static int transmit_notify(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- if (call->notify >= 0) {
- ie->data[0] = 0x80 | call->notify;
-@@ -1866,9 +2937,9 @@
- return 0;
- }
-
--static FUNC_DUMP(dump_shift)
-+static void dump_shift(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);
-+ pri_message(ctrl, "%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);
- }
-
- static char *lineinfo2str(int info)
-@@ -1903,21 +2974,21 @@
- return code2str(info, lineinfo, sizeof(lineinfo) / sizeof(lineinfo[0]));
- }
-
--static FUNC_DUMP(dump_line_information)
-+static void dump_line_information(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);
-+ pri_message(ctrl, "%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);
- }
-
--static FUNC_RECV(receive_line_information)
-+static int receive_line_information(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->ani2 = ie->data[0];
- return 0;
- }
-
--static FUNC_SEND(transmit_line_information)
-+static int transmit_line_information(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- #if 0 /* XXX Is this IE possible for 4ESS only? XXX */
-- if(pri->switchtype == PRI_SWITCH_ATT4ESS) {
-+ if(ctrl->switchtype == PRI_SWITCH_ATT4ESS) {
- ie->data[0] = 0;
- return 3;
- }
-@@ -1953,53 +3024,54 @@
- return code2str(type, gdtype, sizeof(gdtype) / sizeof(gdtype[0]));
- }
-
--static FUNC_DUMP(dump_generic_digits)
-+static void dump_generic_digits(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int encoding;
- int type;
- int idx;
- int value;
- if (len < 3) {
-- pri_message(pri, "%c Generic Digits (len=%02d): Invalid length\n", prefix, len);
-+ pri_message(ctrl, "%c Generic Digits (len=%02d): Invalid length\n", prefix, len);
- return;
- }
- encoding = (ie->data[0] >> 5) & 7;
- type = ie->data[0] & 0x1F;
-- pri_message(pri, "%c Generic Digits (len=%02d): Encoding %s Type %s\n", prefix, len, gdencoding2str(encoding), gdtype2str(type));
-+ pri_message(ctrl, "%c Generic Digits (len=%02d): Encoding %s Type %s\n", prefix, len, gdencoding2str(encoding), gdtype2str(type));
- if (encoding == 3) { /* Binary */
-- pri_message(pri, "%c Don't know how to handle binary encoding\n");
-+ pri_message(ctrl, "%c Don't know how to handle binary encoding\n",
-+ prefix);
- return;
- }
- if (len == 3) /* No number information */
- return;
-- pri_message(pri, "%c Digits: ");
-+ pri_message(ctrl, "%c Digits: ", prefix);
- value = 0;
- for(idx = 3; idx < len; ++idx) {
- switch(encoding) {
- case 0: /* BCD even */
- case 1: /* BCD odd */
-- pri_message(pri, "%d", ie->data[idx-2] & 0x0f);
-+ pri_message(ctrl, "%d", ie->data[idx-2] & 0x0f);
- value = value * 10 + (ie->data[idx-2] & 0x0f);
- if(!encoding || (idx+1 < len)) { /* Special handling for BCD odd */
-- pri_message(pri, "%d", (ie->data[idx-2] >> 4) & 0x0f);
-+ pri_message(ctrl, "%d", (ie->data[idx-2] >> 4) & 0x0f);
- value = value * 10 + ((ie->data[idx-2] >> 4) & 0x0f);
- }
- break;
- case 2: /* IA5 */
-- pri_message(pri, "%c", ie->data[idx-2]);
-+ pri_message(ctrl, "%c", ie->data[idx-2]);
- value = value * 10 + ie->data[idx-2] - '0';
- break;
- }
- }
- switch(type) {
- case 4: /* Info Digits */
-- pri_message(pri, " - %s", lineinfo2str(value));
-+ pri_message(ctrl, " - %s", lineinfo2str(value));
- break;
- }
-- pri_message(pri, "\n");
-+ pri_message(ctrl, "\n");
- }
-
--static FUNC_RECV(receive_generic_digits)
-+static int receive_generic_digits(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int encoding;
- int type;
-@@ -2009,13 +3081,13 @@
- char number[260];
-
- if (len < 3) {
-- pri_error(pri, "Invalid length of Generic Digits IE\n");
-+ pri_error(ctrl, "Invalid length of Generic Digits IE\n");
- return -1;
- }
- encoding = (ie->data[0] >> 5) & 7;
- type = ie->data[0] & 0x1F;
- if (encoding == 3) { /* Binary */
-- pri_message(pri, "!! Unable to handle binary encoded Generic Digits IE\n");
-+ pri_message(ctrl, "!! Unable to handle binary encoded Generic Digits IE\n");
- return 0;
- }
- if (len == 3) /* No number information */
-@@ -2063,10 +3135,13 @@
- break;
- #if 0
- case 5: /* Callid */
-- if (!call->callernum[0]) {
-- memcpy(call->callernum, number, sizeof(call->callernum)-1);
-- call->callerpres = 0;
-- call->callerplan = 0;
-+ if (!call->remote_id.number.valid) {</