osmo-cc-misdn-endpoint/src/libmisdnuser/suppserv/fac.c

880 lines
25 KiB
C

/*
* fac.c
*
* Copyright (C) 2006, Nadi Sarrar
* Nadi Sarrar <nadi@beronet.com>
*
* Portions of this file are based on the mISDN sources
* by Karsten Keil.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "asn1.h"
#include "diversion.h"
#include <mISDN/q931.h>
#include "ccbs.h"
#include "ect.h"
#include "3pty.h"
#include <string.h>
#define AOC_MAX_NUM_CHARGE_UNITS 0xFFFFFF
#define AOCE_CHARGE_UNIT_IE_LENGTH 17
#define AOCD_CHARGE_UNIT_IE_LENGTH 20
enum {
SUPPLEMENTARY_SERVICE = 0x91, /* remote operations protocol */
} SERVICE_DISCRIMINATOR;
/* ******************************************************************* */
/*!
* \brief Encode the head of the Facility component message.
*
* \param p Start of the Facility message
* \param componentType Component-Type value
*
* \return Position for the next octet in the message
*/
__u8 *encodeComponent_Head(__u8 * p, enum asn1ComponentTag componentTag)
{
*p++ = IE_FACILITY; /* Facility IE identifier */
*p++ = 0; /* length -- not known yet */
*p++ = SUPPLEMENTARY_SERVICE; /* remote operations protocol */
*p++ = componentTag;
*p++ = 0; /* length -- not known yet */
return p;
} /* end encodeComponent_Head() */
/* ******************************************************************* */
/*!
* \brief Encode the head of the Facility component message
* with a length that can take a full __u8 value.
*
* \param p Start of the Facility message
* \param componentType Component-Type value
*
* \return Position for the next octet in the message
*/
__u8 *encodeComponent_Head_Long_u8(__u8 * p, enum asn1ComponentTag componentTag)
{
*p++ = IE_FACILITY; /* Facility IE identifier */
*p++ = 0; /* length -- not known yet */
*p++ = SUPPLEMENTARY_SERVICE; /* remote operations protocol */
*p++ = componentTag;
p += ASN1_NUM_OCTETS_LONG_LENGTH_u8; /* length -- not known yet */
return p;
} /* end encodeComponent_Head_Long_u8() */
/* ******************************************************************* */
/*!
* \brief Fill in the final length for the Facility IE contents.
*
* \param msg Beginning of the Facility IE contents.
* \param p Pointer to the next octet of the Facility IE
* contents if there were more.
*
* \return Length of the Facility IE message
*/
int encodeComponent_Length(__u8 * msg, __u8 * p)
{
msg[4] = p - &msg[5];
msg[1] = p - &msg[2];
return msg[1] + 2;
} /* end encodeComponent_Length() */
/* ******************************************************************* */
/*!
* \brief Fill in the final length for the Facility IE contents
* with a length that can take a full __u8 value.
*
* \param msg Beginning of the Facility IE contents.
* \param p Pointer to the next octet of the Facility IE
* contents if there were more.
*
* \return Length of the Facility IE message
*/
int encodeComponent_Length_Long_u8(__u8 * msg, __u8 * p)
{
encodeLen_Long_u8(&msg[4], p - &msg[4 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
msg[1] = p - &msg[2];
return msg[1] + 2;
} /* end encodeComponent_Length_Long_u8() */
/* ******************************************************************* */
/*!
* \brief Encode the Facility ie component operation-value.
*
* \param dest Where to put the operation-value
* \param operationValue enum operation-value to encode
*
* \return Length of the operation-value
*/
int encodeOperationValue(__u8 * dest, int operationValue)
{
struct asn1Oid operationOid;
if (IsEnumOid(operationValue)
&& ConvertEnumToOid(&operationOid, operationValue)) {
return encodeOid(dest, ASN1_TAG_OBJECT_IDENTIFIER, &operationOid);
} else {
return encodeInt(dest, ASN1_TAG_INTEGER, operationValue);
}
} /* end encodeOperationValue() */
/* ******************************************************************* */
/*!
* \brief Encode the Facility ie component error-value.
*
* \param dest Where to put the error-value
* \param errorValue enum error-value to encode
*
* \return Length of the error-value
*/
int encodeErrorValue(__u8 * dest, int errorValue)
{
return encodeOperationValue(dest, errorValue);
} /* end encodeErrorValue() */
/* ******************************************************************* */
/*!
* \brief Encode the common invoke component beginning
*
* \param Dest Where to put the encoding
* \param InvokeID
* \param OperationValue
*
* \return Position for the next octet in the message
*/
__u8 *encodeComponentInvoke_Head(__u8 * Dest, int InvokeID, enum Operation OperationValue)
{
__u8 *p;
p = encodeComponent_Head(Dest, asn1ComponentTag_Invoke);
p += encodeInt(p, ASN1_TAG_INTEGER, InvokeID);
//p += encodeInt(p, ASN1_TAG_CONTEXT_SPECIFIC | 0, LinkedID); /* Optional */
p += encodeOperationValue(p, OperationValue);
return p;
} /* end encodeComponentInvoke_Head() */
/* ******************************************************************* */
/*!
* \brief Encode the common invoke component beginning
* with a length that can take a full __u8 value.
*
* \param Dest Where to put the encoding
* \param InvokeID
* \param OperationValue
*
* \return Position for the next octet in the message
*/
__u8 *encodeComponentInvoke_Head_Long_u8(__u8 * Dest, int InvokeID, enum Operation OperationValue)
{
__u8 *p;
p = encodeComponent_Head_Long_u8(Dest, asn1ComponentTag_Invoke);
p += encodeInt(p, ASN1_TAG_INTEGER, InvokeID);
//p += encodeInt(p, ASN1_TAG_CONTEXT_SPECIFIC | 0, LinkedID); /* Optional */
p += encodeOperationValue(p, OperationValue);
return p;
} /* end encodeComponentInvoke_Head_Long_u8() */
static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm *pc, int numberOfUnits)
{
/* Manually encoded ASN.1 */
unsigned char len = 0;
int i = 0;
int result = -1;
__u8 *p = dest;
if ((p != NULL) && (numberOfUnits <= AOC_MAX_NUM_CHARGE_UNITS)) {
if (numberOfUnits > 0xFFFF)
len = 3;
else if (numberOfUnits > 0xFF)
len = 2;
else
len = 1;
p[i++] = IE_FACILITY; // IE identifier
p[i++] = 0x00; // length -- not known yet
p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol
p[i++] = 0xa1; // invoke component
p[i++] = 0x00; // length -- not known yet
p[i++] = 0x02; // Invoke ID
p[i++] = 0x01; // InvokeId Length
p[i++] = pc->u.inv.invokeId;
p[i++] = 0x02; // Operation Tag
p[i++] = 0x01; // Tag Length
p[i++] = Fac_AOCDChargingUnit; // Operation Value
p[i++] = 0x30;
p[i++] = (0x09 + len); // Length
p[i++] = 0xa1; // APDU
p[i++] = (0x04 + len); // Length
p[i++] = 0x30;
p[i++] = (0x02 + len);
p[i++] = 0x02; // Operation Tag
p[i++] = 0x01; // AOC-D so Sub-Total
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
p[i] = numberOfUnits & 0xFF;
if (len > 1)
p[i+1] = (numberOfUnits >> 8) & 0xFF;
if (len > 2)
p[i+2] = (numberOfUnits >> 16) & 0xFF;
i += len;
p[i++] = 0x82;
p[i++] = 0x01;
p[i++] = 0x01;
p[1] = (AOCD_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
p[4] = p[1] - 3; // Invoke Component Length
result = p[1] + 2; // Total Length of IE
}
return result;
}
static int encodeAOCEChargingUnitOperation(__u8 * dest, const struct asn1_parm *pc, int numberOfUnits)
{
/* Manually encoded ASN.1 */
unsigned char len = 0;
int i = 0;
int result = -1;
__u8 *p = dest;
if ((p != NULL) && (numberOfUnits <= AOC_MAX_NUM_CHARGE_UNITS)) {
if (numberOfUnits > 0xFFFF)
len = 3;
else if (numberOfUnits > 0xFF)
len = 2;
else
len = 1;
p[i++] = IE_FACILITY; // IE identifier
p[i++] = 0x00; // length -- not known yet
p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol
p[i++] = 0xa1; // invoke component
p[i++] = 0x00; // length -- not known yet
p[i++] = 0x02; // Invoke ID
p[i++] = 0x01; // InvokeId Length
p[i++] = pc->u.inv.invokeId;
p[i++] = 0x02; // Operation Tag
p[i++] = 0x01; // Tag Length
p[i++] = Fac_AOCEChargingUnit; // Operation Value
p[i++] = 0xa1; // APDU
p[i++] = 0x30;
p[i++] = (0x09 + len); // Length
p[i++] = 0xa1; // APDU
p[i++] = (0x04 + len); // Length
p[i++] = 0x30;
p[i++] = (0x02 + len);
p[i++] = 0x02;
p[i++] = 0x02; // AOC-E so Total
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
p[i] = numberOfUnits & 0xFF;
if (len > 1)
p[i+1] = (numberOfUnits >> 8) & 0xFF;
if (len > 2)
p[i+2] = (numberOfUnits >> 16) & 0xFF;
i += len;
p[1] = (AOCE_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
p[4] = p[1] - 3; // Invoke Component Length
result = p[1] + 2; // Total Length of IE
}
return result;
}
static int encodeFacMcidIvokeRequest(__u8 * dest, const struct asn1_parm *pc)
{
int i = 0;
int result = -1;
__u8 *p = dest;
if (p != NULL) {
p[i++] = IE_FACILITY; // IE identifier
p[i++] = 0x09; // length
p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol
p[i++] = 0xa1; // invoke component
p[i++] = 0x06; // Manually Encoding the MCID
p[i++] = 0x02; // Invoke ID
p[i++] = 0x01; // InvokeId Length
p[i++] = pc->u.inv.invokeId; // Invoke value
p[i++] = 0x02; // Operation Tag
p[i++] = 0x01; // Tag Length
p[i++] = Fac_MaliciousCallId; // Operation Value
result = p[1] + 2; // Total IE Length
}
return result;
}
#if 0
case Fac_RESULT:
len = encodeFacRESULT(dest, pc, &inv->o.RESULT);
break;
case Fac_ERROR:
len = encodeFacERROR(dest, pc, &inv->o.ERROR);
break;
case Fac_REJECT:
len = encodeFacREJECT(dest, pc, &inv->o.REJECT);
break;
#endif
/*
* Facility IE Encoding
*/
static int encodeFacReturnResult(__u8 * dest, const struct asn1_parm *pc)
{
const struct asn1ReturnResult *res = &pc->u.retResult;
int len = -1;
char ops[20];
__u8 *p;
if (res->operationValuePresent)
sprintf(ops,"operation 0x%04x", res->operationValue);
else
sprintf(ops, "no operation value");
dprint(DBGM_ASN1_ENC, "Return result %s Id:%d start encoding\n", ops, res->invokeId);
if (res->operationValuePresent) {
switch (res->operationValue) {
case Fac_Begin3PTY:
len = encodeFacBegin3PTY(dest, pc, NULL);
break;
case Fac_End3PTY:
len = encodeFacEnd3PTY(dest, pc, NULL);
break;
case Fac_StatusRequest:
len = encodeFacStatusRequest(dest, pc, NULL);
break;
case Fac_CCBSStatusRequest:
len = encodeFacCCBSStatusRequest(dest, pc, NULL);
break;
case Fac_CCBSRequest:
len = encodeFacCCBSRequest(dest, pc, NULL);
break;
case Fac_CCBSInterrogate:
len = encodeFacCCBSInterrogate(dest, pc, NULL);
break;
case Fac_CCNRRequest:
len = encodeFacCCNRRequest(dest, pc, NULL);
break;
case Fac_CCNRInterrogate:
len = encodeFacCCNRInterrogate(dest, pc, NULL);
break;
case Fac_CCBS_T_Request:
len = encodeFacCCBS_T_Request(dest, pc, NULL);
break;
case Fac_CCNR_T_Request:
len = encodeFacCCNR_T_Request(dest, pc, NULL);
break;
case Fac_EctLinkIdRequest:
len = encodeFacEctLinkIdRequest(dest, pc, NULL);
break;
case Fac_EctLoopTest:
len = encodeFacEctLoopTest(dest, pc, NULL);
break;
case Fac_InterrogationDiversion:
len = encodeFacInterrogationDiversion(dest, pc, NULL);
break;
case Fac_InterrogateServedUserNumbers:
len = encodeFacInterrogateServedUserNumbers(dest, pc, &res->o.InterrogateServedUserNumbers);
break;
default:
eprint("ReturnResult Function %s not supported yet\n", ops);
return -1;
}
} else {
p = encodeComponent_Head(dest, asn1ComponentTag_Result);
p += encodeInt(p, ASN1_TAG_INTEGER, res->invokeId);
len = encodeComponent_Length(dest, p);
}
if (len < 0)
eprint("Error on encoding ReturnResult %s\n", ops);
else {
dprint(DBGM_ASN1_ENC, "ReturnResult %s encoded in %d bytes\n", ops, len);
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
}
return len;
}
/* ******************************************************************* */
/*!
* \internal
* \brief Encode the ERROR response.
*
* \param dest Where to put the encoding
* \param error ERROR parameters
*
* \return Length of the encoding
*/
static int encodeFacReturnError(__u8 * dest, const struct asn1_parm *pc)
{
__u8 *p;
const struct asn1ReturnError *err = &pc->u.retError;
int len = -1;
dprint(DBGM_ASN1_ENC, "Return error Id:%d errorValue 0x%x start encoding\n", err->invokeId, err->errorValue);
p = encodeComponent_Head(dest, asn1ComponentTag_Error);
p += encodeInt(p, ASN1_TAG_INTEGER, err->invokeId);
p += encodeErrorValue(p, err->errorValue);
len = encodeComponent_Length(dest, p);
dprint(DBGM_ASN1_ENC, "ReturnError encoded in %d bytes\n", len);
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
return len;
}
/* ******************************************************************* */
/*!
* \internal
* \brief Encode the REJECT response.
*
* \param dest Where to put the encoding
* \param error REJECT parameters
*
* \return Length of the encoding
*/
static int encodeFacReject(__u8 * dest, const struct asn1_parm *pc)
{
const struct asn1Reject *rej = &pc->u.reject;
int len = -1;
char ids[16];
__u8 *p;
if (rej->invokeIdPresent)
sprintf(ids,"ID 0x%04x", rej->invokeId);
else
sprintf(ids, "no invoke ID");
dprint(DBGM_ASN1_ENC, "Reject %s problem %d value 0x%x start encoding\n", ids, rej->problem, rej->problemValue);
p = encodeComponent_Head(dest, asn1ComponentTag_Reject);
if (rej->invokeIdPresent)
p += encodeInt(p, ASN1_TAG_INTEGER, rej->invokeId);
else
p += encodeNull(p, ASN1_TAG_NULL);
p += encodeInt(p, ASN1_TAG_CONTEXT_SPECIFIC | rej->problem, rej->problemValue);
len = encodeComponent_Length(dest, p);
dprint(DBGM_ASN1_ENC, "Reject encoded in %d bytes\n", len);
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
return len;
}
static int encodeFacInvoke(__u8 * dest, const struct asn1_parm *pc)
{
const struct asn1Invoke *inv = &pc->u.inv;
int len = -1;
dprint(DBGM_ASN1_ENC, "Invoke operation 0x%x Id:%d start encoding\n", inv->operationValue, inv->invokeId);
switch (inv->operationValue) {
case Fac_None:
break;
/* Diversion support */
case Fac_ActivationDiversion:
len = encodeFacActivationDiversion(dest, pc, &inv->o.ActivationDiversion);
break;
case Fac_Begin3PTY:
len = encodeFacBegin3PTY(dest, pc, NULL);
break;
case Fac_End3PTY:
len = encodeFacEnd3PTY(dest, pc, NULL);
break;
case Fac_DeactivationDiversion:
len = encodeFacDeactivationDiversion(dest, pc, &inv->o.DeactivationDiversion);
break;
case Fac_ActivationStatusNotificationDiv:
len = encodeFacActivationStatusNotificationDiv(dest, pc, &inv->o.ActivationStatusNotificationDiv);
break;
case Fac_DeactivationStatusNotificationDiv:
len = encodeFacDeactivationStatusNotificationDiv(dest, pc, &inv->o.DeactivationStatusNotificationDiv);
break;
case Fac_InterrogationDiversion:
len = encodeFacInterrogationDiversion(dest, pc, &inv->o.InterrogationDiversion);
break;
case Fac_DiversionInformation:
len = encodeFacDiversionInformation(dest, pc, &inv->o.DiversionInformation);
break;
case Fac_CallDeflection:
len = encodeFacCallDeflection(dest, pc, &inv->o.CallDeflection);
break;
case Fac_CallRerouteing:
len = encodeFacCallRerouteing(dest, pc, &inv->o.CallRerouteing);
break;
case Fac_InterrogateServedUserNumbers:
len = encodeFacInterrogateServedUserNumbers(dest, pc, NULL);
break;
case Fac_DivertingLegInformation1:
len = encodeFacDivertingLegInformation1(dest, pc, &inv->o.DivertingLegInformation1);
break;
case Fac_DivertingLegInformation2:
len = encodeFacDivertingLegInformation2(dest, pc, &inv->o.DivertingLegInformation2);
break;
case Fac_DivertingLegInformation3:
len = encodeFacDivertingLegInformation3(dest, pc, &inv->o.DivertingLegInformation3);
break;
/* ECT support */
case Fac_EctExecute:
len = encodeFacEctExecute(dest, pc, NULL);
break;
case Fac_ExplicitEctExecute:
len = encodeFacExplicitEctExecute(dest, pc, &inv->o.ExplicitEctExecute);
break;
case Fac_RequestSubaddress:
len = encodeFacRequestSubaddress(dest, pc, NULL);
break;
case Fac_SubaddressTransfer:
len = encodeFacSubaddressTransfer(dest, pc, &inv->o.SubaddressTransfer);
break;
case Fac_EctLinkIdRequest:
len = encodeFacEctLinkIdRequest(dest, pc, NULL);
break;
case Fac_EctInform:
len = encodeFacEctInform(dest, pc, &inv->o.EctInform);
break;
case Fac_EctLoopTest:
len = encodeFacEctLoopTest(dest, pc, &inv->o.EctLoopTest);
break;
/* AOC support */
case Fac_ChargingRequest:
case Fac_AOCSCurrency:
case Fac_AOCSSpecialArr:
case Fac_AOCDCurrency:
case Fac_AOCECurrency:
break;
case Fac_AOCDChargingUnit:
len = encodeAOCDChargingUnitOperation(dest, pc, inv->o.AOCchu.recordedUnits);
break;
case Fac_AOCEChargingUnit:
len = encodeAOCEChargingUnitOperation(dest, pc, inv->o.AOCchu.recordedUnits);
break;
/* Malicious Call Tag Support */
case Fac_MaliciousCallId:
len = encodeFacMcidIvokeRequest(dest, pc);
break;
case Fac_StatusRequest:
len = encodeFacStatusRequest(dest, pc, &inv->o.StatusRequest);
break;
/* CCBS/CCNR support */
case Fac_CallInfoRetain:
len = encodeFacCallInfoRetain(dest, pc, &inv->o.CallInfoRetain);
break;
case Fac_EraseCallLinkageID:
len = encodeFacEraseCallLinkageID(dest, pc, &inv->o.EraseCallLinkageID);
break;
case Fac_CCBSDeactivate:
len = encodeFacCCBSDeactivate(dest, pc, &inv->o.CCBSDeactivate);
break;
case Fac_CCBSErase:
len = encodeFacCCBSErase(dest, pc, &inv->o.CCBSErase);
break;
case Fac_CCBSRemoteUserFree:
len = encodeFacCCBSRemoteUserFree(dest, pc, &inv->o.CCBSRemoteUserFree);
break;
case Fac_CCBSCall:
len = encodeFacCCBSCall(dest, pc, &inv->o.CCBSCall);
break;
case Fac_CCBSStatusRequest:
len = encodeFacCCBSStatusRequest(dest, pc, &inv->o.CCBSStatusRequest);
break;
case Fac_CCBSBFree:
len = encodeFacCCBSBFree(dest, pc, &inv->o.CCBSBFree);
break;
case Fac_CCBSStopAlerting:
len = encodeFacCCBSStopAlerting(dest, pc, &inv->o.CCBSStopAlerting);
break;
case Fac_CCBSRequest:
len = encodeFacCCBSRequest(dest, pc, &inv->o.CCBSRequest);
break;
case Fac_CCBSInterrogate:
len = encodeFacCCBSInterrogate(dest, pc, &inv->o.CCBSInterrogate);
break;
case Fac_CCNRRequest:
len = encodeFacCCNRRequest(dest, pc, &inv->o.CCNRRequest);
break;
case Fac_CCNRInterrogate:
len = encodeFacCCNRInterrogate(dest, pc, &inv->o.CCNRInterrogate);
break;
/* CCBS-T/CCNR-T support */
case Fac_CCBS_T_Call:
len = encodeFacCCBS_T_Call(dest, pc, NULL);
break;
case Fac_CCBS_T_Suspend:
len = encodeFacCCBS_T_Suspend(dest, pc, NULL);
break;
case Fac_CCBS_T_Resume:
len = encodeFacCCBS_T_Resume(dest, pc, NULL);
break;
case Fac_CCBS_T_RemoteUserFree:
len = encodeFacCCBS_T_RemoteUserFree(dest, pc, NULL);
break;
case Fac_CCBS_T_Available:
len = encodeFacCCBS_T_Available(dest, pc, NULL);
break;
case Fac_CCBS_T_Request:
len = encodeFacCCBS_T_Request(dest, pc, &inv->o.CCBS_T_Request);
break;
case Fac_CCNR_T_Request:
len = encodeFacCCNR_T_Request(dest, pc, &inv->o.CCNR_T_Request);
break;
default:
eprint("Function %d not supported yet\n", inv->operationValue);
return -1;
}
if (len < 0)
eprint("Error on encoding function 0x%x\n", inv->operationValue);
else {
dprint(DBGM_ASN1_ENC, "Function 0x%x encoded in %d bytes\n", inv->operationValue, len);
dhexprint(DBGM_ASN1_DATA, "Facility:", dest, len);
}
return len;
}
int encodeFac(__u8 * dest, struct asn1_parm *ap)
{
int len = -1;
if (ap->Valid) {
switch (ap->comp) {
case CompInvoke:
len = encodeFacInvoke(dest, ap);
break;
case CompReturnResult:
len = encodeFacReturnResult(dest, ap);
break;
case CompReturnError:
len = encodeFacReturnError(dest, ap);
break;
case CompReject:
len = encodeFacReject(dest, ap);
break;
default:
eprint("Unknown component 0x%x\n", ap->comp);
break;
}
} else
eprint("Facility struct component(%d) not marked as valid\n", ap->comp);
return len;
}
/*
* Facility IE Decoding
*/
int decodeFac(__u8 * src, struct asn1_parm *ap)
{
unsigned fac_len;
__u8 *end;
__u8 *p = src;
if (!p) {
goto _dec_err;
}
fac_len = *p++;
end = p + fac_len;
if (*p++ != SUPPLEMENTARY_SERVICE) {
goto _dec_err;
}
memset(ap, 0, sizeof(*ap));
if (ParseComponent(ap, p, end) == -1) {
goto _dec_err;
}
switch (ap->comp) {
case CompInvoke:
switch (ap->u.inv.operationValue) {
/* Diversion support */
case Fac_ActivationDiversion:
case Fac_DeactivationDiversion:
case Fac_ActivationStatusNotificationDiv:
case Fac_DeactivationStatusNotificationDiv:
case Fac_InterrogationDiversion:
case Fac_DiversionInformation:
case Fac_CallDeflection:
case Fac_CallRerouteing:
case Fac_InterrogateServedUserNumbers:
case Fac_DivertingLegInformation1:
case Fac_DivertingLegInformation2:
case Fac_DivertingLegInformation3:
/* ECT support */
case Fac_EctExecute:
case Fac_ExplicitEctExecute:
case Fac_RequestSubaddress:
case Fac_SubaddressTransfer:
case Fac_EctLinkIdRequest:
case Fac_EctInform:
case Fac_EctLoopTest:
/* AOC support */
case Fac_AOCDCurrency:
case Fac_AOCECurrency:
case Fac_AOCDChargingUnit:
case Fac_AOCEChargingUnit:
case Fac_StatusRequest:
/* CCBS/CCNR support */
case Fac_CallInfoRetain:
case Fac_EraseCallLinkageID:
case Fac_CCBSDeactivate:
case Fac_CCBSErase:
case Fac_CCBSRemoteUserFree:
case Fac_CCBSCall:
case Fac_CCBSStatusRequest:
case Fac_CCBSBFree:
case Fac_CCBSStopAlerting:
case Fac_CCBSRequest:
case Fac_CCBSInterrogate:
case Fac_CCNRRequest:
case Fac_CCNRInterrogate:
/* CCBS-T/CCNR-T support */
case Fac_CCBS_T_Call:
case Fac_CCBS_T_Suspend:
case Fac_CCBS_T_Resume:
case Fac_CCBS_T_RemoteUserFree:
case Fac_CCBS_T_Available:
case Fac_CCBS_T_Request:
case Fac_CCNR_T_Request:
ap->Valid = 1;
return 0;
default:
eprint("Unknown invoke operation %x\n", ap->u.inv.operationValue);
break;
}
break;
/* ------------------------------------------------------------------- */
case CompReturnResult:
if (!ap->u.retResult.operationValuePresent) {
return 0;
}
switch (ap->u.retResult.operationValue) {
/* Diversion support */
case Fac_ActivationDiversion:
case Fac_DeactivationDiversion:
case Fac_InterrogationDiversion:
case Fac_CallDeflection:
case Fac_CallRerouteing:
case Fac_InterrogateServedUserNumbers:
ap->Valid = 1;
return 0;
case Fac_ActivationStatusNotificationDiv:
case Fac_DeactivationStatusNotificationDiv:
case Fac_DiversionInformation:
case Fac_DivertingLegInformation1:
case Fac_DivertingLegInformation2:
case Fac_DivertingLegInformation3:
break;
/* ECT support */
case Fac_EctExecute:
case Fac_ExplicitEctExecute:
case Fac_RequestSubaddress:
case Fac_SubaddressTransfer:
break;
case Fac_EctLinkIdRequest:
return 0;
case Fac_EctInform:
break;
case Fac_EctLoopTest:
return 0;
/* AOC support */
case Fac_ChargingRequest:
case Fac_AOCSCurrency:
case Fac_AOCSSpecialArr:
case Fac_AOCDCurrency:
case Fac_AOCDChargingUnit:
case Fac_AOCECurrency:
case Fac_AOCEChargingUnit:
break;
case Fac_StatusRequest:
return 0;
/* CCBS/CCNR support */
case Fac_CallInfoRetain:
case Fac_EraseCallLinkageID:
break;
case Fac_CCBSDeactivate:
return 0;
case Fac_CCBSErase:
case Fac_CCBSRemoteUserFree:
case Fac_CCBSCall:
break;
case Fac_CCBSStatusRequest:
return 0;
case Fac_CCBSBFree:
case Fac_CCBSStopAlerting:
break;
case Fac_CCBSRequest:
case Fac_CCBSInterrogate:
case Fac_CCNRRequest:
case Fac_CCNRInterrogate:
return 0;
/* CCBS-T/CCNR-T support */
case Fac_CCBS_T_Call:
case Fac_CCBS_T_Suspend:
case Fac_CCBS_T_Resume:
case Fac_CCBS_T_RemoteUserFree:
case Fac_CCBS_T_Available:
break;
case Fac_CCBS_T_Request:
case Fac_CCNR_T_Request:
return 0;
default:
break;
} /* end switch */
break;
/* ------------------------------------------------------------------- */
case CompReturnError:
ap->Valid = 1;
return 0;
/* ------------------------------------------------------------------- */
case CompReject:
ap->Valid = 1;
return 0;
} /* end switch */
_dec_err:
return -1;
} /* end decodeFac() */