1570 lines
48 KiB
C
1570 lines
48 KiB
C
/*
|
|
*
|
|
* Diversion Supplementary Services ETS 300 207-1 Table 3
|
|
*
|
|
* Diversion Facility ie encode/decode
|
|
*
|
|
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
|
* version 2.1 as published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
|
|
*
|
|
*/
|
|
|
|
#include "asn1.h"
|
|
#include "diversion.h"
|
|
#include <string.h>
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the Q.931 ie UserUser value used for Diversion.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param Q931ie Q931 ie information to encode.
|
|
*
|
|
* \retval length
|
|
*/
|
|
static int encodeQ931_Div_UserInfo(__u8 * Dest, const struct Q931_UserUserInformation *Q931ie)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
|
|
/* [APPLICATION 0] IMPLICIT OCTET STRING */
|
|
Dest[0] = ASN1_TAG_APPLICATION_WIDE | 0;
|
|
|
|
/* Pre-calculate content length */
|
|
if (Q931ie->Length) {
|
|
Length = 2 + Q931ie->Length;
|
|
} else {
|
|
Length = 0;
|
|
}
|
|
|
|
/* Store length */
|
|
if (Length < 0x80) {
|
|
Dest[1] = Length;
|
|
p = &Dest[2];
|
|
} else {
|
|
encodeLen_Long_u8(&Dest[1], Length);
|
|
p = &Dest[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
}
|
|
|
|
/* Store value */
|
|
if (Q931ie->Length) {
|
|
*p++ = 0x7E; /* Q.931 User-User-Information ie tag */
|
|
*p++ = Q931ie->Length;
|
|
memcpy(p, Q931ie->Contents, Q931ie->Length);
|
|
p += Q931ie->Length;
|
|
}
|
|
|
|
return p - Dest;
|
|
} /* end encodeQ931_Div_UserInfo() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Parse the Q.931 argument contents for Diversion.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param Q931ie Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
static int ParseQ931_Div_UserInfo(struct asn1_parm *pc, u_char * p, u_char * end, struct Q931_UserUserInformation *Q931ie)
|
|
{
|
|
__u8 Ie_type;
|
|
size_t Length;
|
|
INIT;
|
|
|
|
memset(Q931ie, 0, sizeof(*Q931ie));
|
|
do {
|
|
if (end < p + 2) {
|
|
/* Q.931 ie length error */
|
|
return -1;
|
|
}
|
|
Ie_type = *p++;
|
|
Length = *p++;
|
|
if (end < p + Length) {
|
|
/* Q.931 ie length error */
|
|
return -1;
|
|
}
|
|
switch (Ie_type) {
|
|
case 0x7E: /* Q.931 User-User-Information ie tag */
|
|
if (Length <= sizeof(Q931ie->Contents)) {
|
|
Q931ie->Length = Length;
|
|
memcpy(Q931ie->Contents, p, Length);
|
|
}
|
|
break;
|
|
default:
|
|
/* Unknown Q.931 ie in Diversion message */
|
|
break;
|
|
} /* end switch */
|
|
p += Length;
|
|
} while (p < end);
|
|
|
|
return p - beg;
|
|
} /* end ParseQ931_Div_UserInfo() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the Q.931 ie value used for Diversion.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param Q931ie Q931 ie information to encode.
|
|
*
|
|
* \retval length
|
|
*/
|
|
static int encodeQ931_Div(__u8 * Dest, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
|
|
/* [APPLICATION 0] IMPLICIT OCTET STRING */
|
|
Dest[0] = ASN1_TAG_APPLICATION_WIDE | 0;
|
|
|
|
/* Pre-calculate content length */
|
|
Length = 0;
|
|
if (Q931ie->Bc.Length) {
|
|
Length += 2 + Q931ie->Bc.Length;
|
|
}
|
|
if (Q931ie->Hlc.Length) {
|
|
Length += 2 + Q931ie->Hlc.Length;
|
|
}
|
|
if (Q931ie->Llc.Length) {
|
|
Length += 2 + Q931ie->Llc.Length;
|
|
}
|
|
if (Q931ie->UserInfo.Length) {
|
|
Length += 2 + Q931ie->UserInfo.Length;
|
|
}
|
|
|
|
/* Store length */
|
|
if (Length < 0x80) {
|
|
Dest[1] = Length;
|
|
p = &Dest[2];
|
|
} else {
|
|
encodeLen_Long_u8(&Dest[1], Length);
|
|
p = &Dest[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
}
|
|
|
|
/* Store value */
|
|
if (Q931ie->Bc.Length) {
|
|
*p++ = 0x04; /* Q.931 Bearer Capability ie tag */
|
|
*p++ = Q931ie->Bc.Length;
|
|
memcpy(p, Q931ie->Bc.Contents, Q931ie->Bc.Length);
|
|
p += Q931ie->Bc.Length;
|
|
}
|
|
if (Q931ie->Llc.Length) {
|
|
*p++ = 0x7C; /* Q.931 Low Layer Compatibility ie tag */
|
|
*p++ = Q931ie->Llc.Length;
|
|
memcpy(p, Q931ie->Llc.Contents, Q931ie->Llc.Length);
|
|
p += Q931ie->Llc.Length;
|
|
}
|
|
if (Q931ie->Hlc.Length) {
|
|
*p++ = 0x7D; /* Q.931 High Layer Compatibility ie tag */
|
|
*p++ = Q931ie->Hlc.Length;
|
|
memcpy(p, Q931ie->Hlc.Contents, Q931ie->Hlc.Length);
|
|
p += Q931ie->Hlc.Length;
|
|
}
|
|
if (Q931ie->UserInfo.Length) {
|
|
*p++ = 0x7E; /* Q.931 User-User-Information ie tag */
|
|
*p++ = Q931ie->UserInfo.Length;
|
|
memcpy(p, Q931ie->UserInfo.Contents, Q931ie->UserInfo.Length);
|
|
p += Q931ie->UserInfo.Length;
|
|
}
|
|
|
|
return p - Dest;
|
|
} /* end encodeQ931_Div() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Parse the Q.931 argument contents for Diversion.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param Q931ie Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
static int ParseQ931_Div(struct asn1_parm *pc, u_char * p, u_char * end, struct Q931_Bc_Hlc_Llc_Uu *Q931ie)
|
|
{
|
|
__u8 Ie_type;
|
|
size_t Length;
|
|
INIT;
|
|
|
|
memset(Q931ie, 0, sizeof(*Q931ie));
|
|
do {
|
|
if (end < p + 2) {
|
|
/* Q.931 ie length error */
|
|
return -1;
|
|
}
|
|
Ie_type = *p++;
|
|
Length = *p++;
|
|
if (end < p + Length) {
|
|
/* Q.931 ie length error */
|
|
return -1;
|
|
}
|
|
switch (Ie_type) {
|
|
case 0x04: /* Q.931 Bearer Capability ie tag */
|
|
if (Length <= sizeof(Q931ie->Bc.Contents)) {
|
|
Q931ie->Bc.Length = Length;
|
|
memcpy(Q931ie->Bc.Contents, p, Length);
|
|
}
|
|
break;
|
|
case 0x7C: /* Q.931 Low Layer Compatibility ie tag */
|
|
if (Length <= sizeof(Q931ie->Llc.Contents)) {
|
|
Q931ie->Llc.Length = Length;
|
|
memcpy(Q931ie->Llc.Contents, p, Length);
|
|
}
|
|
break;
|
|
case 0x7D: /* Q.931 High Layer Compatibility ie tag */
|
|
if (Length <= sizeof(Q931ie->Hlc.Contents)) {
|
|
Q931ie->Hlc.Length = Length;
|
|
memcpy(Q931ie->Hlc.Contents, p, Length);
|
|
}
|
|
break;
|
|
case 0x7E: /* Q.931 User-User-Information ie tag */
|
|
if (Length <= sizeof(Q931ie->UserInfo.Contents)) {
|
|
Q931ie->UserInfo.Length = Length;
|
|
memcpy(Q931ie->UserInfo.Contents, p, Length);
|
|
}
|
|
break;
|
|
default:
|
|
/* Unknown Q.931 ie in Diversion message */
|
|
break;
|
|
} /* end switch */
|
|
p += Length;
|
|
} while (p < end);
|
|
|
|
return p - beg;
|
|
} /* end ParseQ931_Div() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the ServedUserNr type.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param ServedUser Served user number information to encode.
|
|
*
|
|
* \retval length
|
|
*/
|
|
static int encodeServedUserNumber_Full(__u8 * Dest, const struct FacPartyNumber *ServedUser)
|
|
{
|
|
int Length;
|
|
|
|
if (ServedUser->LengthOfNumber) {
|
|
/* Forward this number */
|
|
Length = encodePartyNumber_Full(Dest, ServedUser);
|
|
} else {
|
|
/* Forward all numbers */
|
|
Length = encodeNull(Dest, ASN1_TAG_NULL);
|
|
}
|
|
|
|
return Length;
|
|
} /* end encodeServedUserNumber_Full() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the ServedUserNr argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param ServedUser Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
static int ParseServedUserNumber_Full(struct asn1_parm *pc, u_char * p, u_char * end, struct FacPartyNumber *ServedUser)
|
|
{
|
|
INIT;
|
|
|
|
ServedUser->LengthOfNumber = 0;
|
|
XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED);
|
|
|
|
/* Must be a PartyNumber (Which is itself a CHOICE) */
|
|
return ParsePartyNumber_Full(pc, beg, end, ServedUser);
|
|
} /* end ParseServedUserNumber_Full() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the IntResult type.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param IntResult Forwarding record information to encode.
|
|
*
|
|
* \retval length
|
|
*/
|
|
static int encodeIntResult(__u8 * Dest, const struct FacForwardingRecord *IntResult)
|
|
{
|
|
__u8 *p;
|
|
|
|
Dest[0] = ASN1_TAG_SEQUENCE;
|
|
p = &Dest[2];
|
|
|
|
p += encodeServedUserNumber_Full(p, &IntResult->ServedUser);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, IntResult->BasicService);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, IntResult->Procedure);
|
|
p += encodeAddress_Full(p, &IntResult->ForwardedTo);
|
|
|
|
/* length */
|
|
Dest[1] = p - &Dest[2];
|
|
|
|
return p - Dest;
|
|
} /* end encodeIntResult() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Parse the IntResult argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param IntResult Forwarding record storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
static int ParseIntResult(struct asn1_parm *pc, u_char * p, u_char * end, struct FacForwardingRecord *IntResult)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseServedUserNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &IntResult->ServedUser);
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
IntResult->BasicService = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
IntResult->Procedure = Value;
|
|
XSEQUENCE_1(ParseAddress_Full, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &IntResult->ForwardedTo);
|
|
|
|
return p - beg;
|
|
} /* end ParseIntResult() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the IntResultList type.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param IntResultList Forwarding record list information to encode.
|
|
*
|
|
* \retval length
|
|
*/
|
|
static int encodeIntResultList(__u8 * Dest, const struct FacForwardingList *IntResultList)
|
|
{
|
|
unsigned Index;
|
|
__u8 *p;
|
|
|
|
Dest[0] = ASN1_TAG_SET;
|
|
p = &Dest[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
|
|
for (Index = 0; Index < IntResultList->NumRecords; ++Index) {
|
|
p += encodeIntResult(p, &IntResultList->List[Index]);
|
|
} /* end for */
|
|
|
|
/* length */
|
|
encodeLen_Long_u8(&Dest[1], p - &Dest[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
|
|
|
return p - Dest;
|
|
} /* end encodeIntResultList() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the IntResultList argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param IntResultList Forwarding record list storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseIntResultList(struct asn1_parm *pc, u_char * p, u_char * end, struct FacForwardingList *IntResultList)
|
|
{
|
|
INIT;
|
|
|
|
IntResultList->NumRecords = 0;
|
|
while (p < end) {
|
|
if (IntResultList->NumRecords < sizeof(IntResultList->List) / sizeof(IntResultList->List[0])) {
|
|
XSEQUENCE_1(ParseIntResult, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED,
|
|
&IntResultList->List[IntResultList->NumRecords]);
|
|
++IntResultList->NumRecords;
|
|
} else {
|
|
/* Too many records */
|
|
return -1;
|
|
}
|
|
} /* end while */
|
|
|
|
return p - beg;
|
|
} /* end ParseIntResultList() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the ServedUserNumberList type.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param ServedUserNumberList Served user record list information to encode.
|
|
*
|
|
* \retval length
|
|
*/
|
|
static int encodeServedUserNumberList(__u8 * Dest, const struct FacServedUserNumberList *ServedUserNumberList)
|
|
{
|
|
unsigned Index;
|
|
__u8 *p;
|
|
|
|
Dest[0] = ASN1_TAG_SET;
|
|
p = &Dest[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
|
|
for (Index = 0; Index < ServedUserNumberList->NumRecords; ++Index) {
|
|
p += encodePartyNumber_Full(p, &ServedUserNumberList->List[Index]);
|
|
} /* end for */
|
|
|
|
/* length */
|
|
encodeLen_Long_u8(&Dest[1], p - &Dest[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
|
|
|
return p - Dest;
|
|
} /* end encodeServedUserNumberList() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the ServedUserNumberList argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param ServedUserNumberList Served user record list storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseServedUserNumberList(struct asn1_parm *pc, u_char * p, u_char * end, struct FacServedUserNumberList *ServedUserNumberList)
|
|
{
|
|
INIT;
|
|
|
|
ServedUserNumberList->NumRecords = 0;
|
|
while (p < end) {
|
|
if (ServedUserNumberList->NumRecords < sizeof(ServedUserNumberList->List) / sizeof(ServedUserNumberList->List[0])) {
|
|
XSEQUENCE_1(ParsePartyNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED,
|
|
&ServedUserNumberList->List[ServedUserNumberList->NumRecords]);
|
|
++ServedUserNumberList->NumRecords;
|
|
} else {
|
|
/* Too many records */
|
|
return -1;
|
|
}
|
|
} /* end while */
|
|
|
|
return p - beg;
|
|
} /* end ParseServedUserNumberList() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the ActivationDiversion facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param ActivationDiversion Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacActivationDiversion(__u8 * Dest, const struct asn1_parm *pc, const struct FacActivationDiversion *ActivationDiversion)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
switch (pc->comp) {
|
|
case CompInvoke:
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_ActivationDiversion);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, ActivationDiversion->Procedure);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, ActivationDiversion->BasicService);
|
|
p += encodeAddress_Full(p, &ActivationDiversion->ForwardedTo);
|
|
p += encodeServedUserNumber_Full(p, &ActivationDiversion->ServedUser);
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
case CompReturnResult:
|
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeOperationValue(p, Fac_ActivationDiversion);
|
|
|
|
/* No arguments */
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
default:
|
|
Length = -1;
|
|
break;
|
|
} /* end switch */
|
|
|
|
return Length;
|
|
} /* end encodeFacActivationDiversion() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the ActivationDiversion invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param ActivationDiversion Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseActivationDiversion(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacActivationDiversion *ActivationDiversion)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
ActivationDiversion->Procedure = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
ActivationDiversion->BasicService = Value;
|
|
XSEQUENCE_1(ParseAddress_Full, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &ActivationDiversion->ForwardedTo);
|
|
XSEQUENCE_1(ParseServedUserNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &ActivationDiversion->ServedUser);
|
|
|
|
return p - beg;
|
|
} /* end ParseActivationDiversion() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the DeactivationDiversion facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param DeactivationDiversion Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacDeactivationDiversion(__u8 * Dest, const struct asn1_parm *pc, const struct FacDeactivationDiversion *DeactivationDiversion)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
switch (pc->comp) {
|
|
case CompInvoke:
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_DeactivationDiversion);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DeactivationDiversion->Procedure);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DeactivationDiversion->BasicService);
|
|
p += encodeServedUserNumber_Full(p, &DeactivationDiversion->ServedUser);
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
case CompReturnResult:
|
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeOperationValue(p, Fac_DeactivationDiversion);
|
|
|
|
/* No arguments */
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
default:
|
|
Length = -1;
|
|
break;
|
|
} /* end switch */
|
|
|
|
return Length;
|
|
} /* end encodeFacDeactivationDiversion() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the DeactivationDiversion invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param DeactivationDiversion Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseDeactivationDiversion(struct asn1_parm *pc, u_char * p, u_char * end, struct FacDeactivationDiversion *DeactivationDiversion)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DeactivationDiversion->Procedure = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DeactivationDiversion->BasicService = Value;
|
|
XSEQUENCE_1(ParseServedUserNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &DeactivationDiversion->ServedUser);
|
|
|
|
return p - beg;
|
|
} /* end ParseDeactivationDiversion() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the ActivationStatusNotificationDiv facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param ActivationStatusNotificationDiv Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacActivationStatusNotificationDiv(__u8 * Dest, const struct asn1_parm *pc,
|
|
const struct FacActivationStatusNotificationDiv *ActivationStatusNotificationDiv)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_ActivationStatusNotificationDiv);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, ActivationStatusNotificationDiv->Procedure);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, ActivationStatusNotificationDiv->BasicService);
|
|
p += encodeAddress_Full(p, &ActivationStatusNotificationDiv->ForwardedTo);
|
|
p += encodeServedUserNumber_Full(p, &ActivationStatusNotificationDiv->ServedUser);
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
|
|
return Length;
|
|
} /* end encodeFacActivationStatusNotificationDiv() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the ActivationStatusNotificationDiv invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param ActivationStatusNotificationDiv Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseActivationStatusNotificationDiv(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacActivationStatusNotificationDiv *ActivationStatusNotificationDiv)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
ActivationStatusNotificationDiv->Procedure = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
ActivationStatusNotificationDiv->BasicService = Value;
|
|
XSEQUENCE_1(ParseAddress_Full, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &ActivationStatusNotificationDiv->ForwardedTo);
|
|
XSEQUENCE_1(ParseServedUserNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &ActivationStatusNotificationDiv->ServedUser);
|
|
|
|
return p - beg;
|
|
} /* end ParseActivationStatusNotificationDiv() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the DeactivationStatusNotificationDiv facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param DeactivationStatusNotificationDiv Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacDeactivationStatusNotificationDiv(__u8 * Dest, const struct asn1_parm *pc,
|
|
const struct FacDeactivationStatusNotificationDiv
|
|
*DeactivationStatusNotificationDiv)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_DeactivationStatusNotificationDiv);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DeactivationStatusNotificationDiv->Procedure);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DeactivationStatusNotificationDiv->BasicService);
|
|
p += encodeServedUserNumber_Full(p, &DeactivationStatusNotificationDiv->ServedUser);
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
|
|
return Length;
|
|
} /* end encodeFacDeactivationStatusNotificationDiv() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the DeactivationStatusNotificationDiv invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param DeactivationStatusNotificationDiv Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseDeactivationStatusNotificationDiv(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacDeactivationStatusNotificationDiv *DeactivationStatusNotificationDiv)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DeactivationStatusNotificationDiv->Procedure = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DeactivationStatusNotificationDiv->BasicService = Value;
|
|
XSEQUENCE_1(ParseServedUserNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &DeactivationStatusNotificationDiv->ServedUser);
|
|
|
|
|
|
return p - beg;
|
|
} /* end ParseDeactivationStatusNotificationDiv() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the InterrogationDiversion facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param InterrogationDiversion Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacInterrogationDiversion(__u8 * Dest, const struct asn1_parm *pc, const struct FacInterrogationDiversion *InterrogationDiversion)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
switch (pc->comp) {
|
|
case CompInvoke:
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_InterrogationDiversion);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, InterrogationDiversion->Procedure);
|
|
if (InterrogationDiversion->BasicService) {
|
|
/* Not the DEFAULT value */
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, InterrogationDiversion->BasicService);
|
|
}
|
|
p += encodeServedUserNumber_Full(p, &InterrogationDiversion->ServedUser);
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
case CompReturnResult:
|
|
p = encodeComponent_Head_Long_u8(Dest, asn1ComponentTag_Result);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
|
|
p += encodeOperationValue(p, Fac_InterrogationDiversion);
|
|
|
|
p += encodeIntResultList(p, &pc->u.retResult.o.InterrogationDiversion);
|
|
|
|
/* sequence Length */
|
|
encodeLen_Long_u8(&SeqStart[1], p - &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
|
|
|
Length = encodeComponent_Length_Long_u8(Dest, p);
|
|
break;
|
|
default:
|
|
Length = -1;
|
|
break;
|
|
} /* end switch */
|
|
|
|
return Length;
|
|
} /* end encodeFacInterrogationDiversion() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the InterrogationDiversion invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param InterrogationDiversion Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseInterrogationDiversion(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacInterrogationDiversion *InterrogationDiversion)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
InterrogationDiversion->Procedure = Value;
|
|
Value = 0; /* DEFAULT BasicService value (allServices) */
|
|
XSEQUENCE_OPT_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
InterrogationDiversion->BasicService = Value;
|
|
XSEQUENCE_1(ParseServedUserNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &InterrogationDiversion->ServedUser);
|
|
|
|
return p - beg;
|
|
} /* end ParseInterrogationDiversion() */
|
|
|
|
/* ******************************************************************* */
|
|
#if 0
|
|
/*!
|
|
* \brief Parse the InterrogationDiversion result parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse parameters
|
|
* \param end End buffer position that must not go past.
|
|
* \param InterrogationDiversion Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseInterrogationDiversion_RES(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacForwardingList *InterrogationDiversion)
|
|
{
|
|
return ParseIntResultList(pc, p, end, InterrogationDiversion);
|
|
} /* end ParseInterrogationDiversion_RES() */
|
|
#endif
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the DiversionInformation facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param DiversionInformation Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacDiversionInformation(__u8 * Dest, const struct asn1_parm *pc, const struct FacDiversionInformation *DiversionInformation)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
__u8 *TagStart;
|
|
|
|
p = encodeComponentInvoke_Head_Long_u8(Dest, pc->u.inv.invokeId, Fac_DiversionInformation);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DiversionInformation->DiversionReason);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DiversionInformation->BasicService);
|
|
if (DiversionInformation->ServedUserSubaddress.Length) {
|
|
p += encodePartySubaddress_Full(p, &DiversionInformation->ServedUserSubaddress);
|
|
}
|
|
if (DiversionInformation->CallingAddressPresent) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 0;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePresentedAddressScreened_Full(p, &DiversionInformation->CallingAddress);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
if (DiversionInformation->OriginalCalledPresent) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePresentedNumberUnscreened_Full(p, &DiversionInformation->OriginalCalled);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
if (DiversionInformation->LastDivertingPresent) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePresentedNumberUnscreened_Full(p, &DiversionInformation->LastDiverting);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
if (DiversionInformation->LastDivertingReasonPresent) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3;
|
|
p = &TagStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DiversionInformation->LastDivertingReason);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
if (DiversionInformation->UserInfo.Length) {
|
|
p += encodeQ931_Div_UserInfo(p, &DiversionInformation->UserInfo);
|
|
}
|
|
|
|
/* sequence Length */
|
|
encodeLen_Long_u8(&SeqStart[1], p - &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
|
|
|
Length = encodeComponent_Length_Long_u8(Dest, p);
|
|
|
|
return Length;
|
|
} /* end encodeFacDiversionInformation() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the DiversionInformation invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param DiversionInformation Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseDiversionInformation(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacDiversionInformation *DiversionInformation)
|
|
{
|
|
int xtag;
|
|
int xlen;
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DiversionInformation->DiversionReason = Value;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DiversionInformation->BasicService = Value;
|
|
|
|
if (p < end && (*p == ASN1_TAG_SEQUENCE || *p == ASN1_TAG_OCTET_STRING)) {
|
|
CallASN1(ret, p, end, ParsePartySubaddress_Full(pc, p, end, &DiversionInformation->ServedUserSubaddress));
|
|
} else {
|
|
DiversionInformation->ServedUserSubaddress.Length = 0;
|
|
}
|
|
|
|
if (p < end && *p == (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 0)) {
|
|
/* Remove EXPLICIT tag */
|
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag));
|
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen));
|
|
CallASN1(ret, p, end, ParsePresentedAddressScreened_Full(pc, p, end, &DiversionInformation->CallingAddress));
|
|
DiversionInformation->CallingAddressPresent = 1;
|
|
} else {
|
|
DiversionInformation->CallingAddressPresent = 0;
|
|
}
|
|
|
|
if (p < end && *p == (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1)) {
|
|
/* Remove EXPLICIT tag */
|
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag));
|
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen));
|
|
CallASN1(ret, p, end, ParsePresentedNumberUnscreened_Full(pc, p, end, &DiversionInformation->OriginalCalled));
|
|
DiversionInformation->OriginalCalledPresent = 1;
|
|
} else {
|
|
DiversionInformation->OriginalCalledPresent = 0;
|
|
}
|
|
|
|
if (p < end && *p == (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2)) {
|
|
/* Remove EXPLICIT tag */
|
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag));
|
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen));
|
|
CallASN1(ret, p, end, ParsePresentedNumberUnscreened_Full(pc, p, end, &DiversionInformation->LastDiverting));
|
|
DiversionInformation->LastDivertingPresent = 1;
|
|
} else {
|
|
DiversionInformation->LastDivertingPresent = 0;
|
|
}
|
|
|
|
if (p < end && *p == (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3)) {
|
|
/* Remove EXPLICIT tag */
|
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag));
|
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen));
|
|
CallASN1(ret, p, end, ParseEnum(pc, p, end, &Value));
|
|
DiversionInformation->LastDivertingReason = Value;
|
|
DiversionInformation->LastDivertingReasonPresent = 1;
|
|
} else {
|
|
DiversionInformation->LastDivertingReasonPresent = 0;
|
|
}
|
|
|
|
DiversionInformation->UserInfo.Length = 0;
|
|
XSEQUENCE_OPT_1(ParseQ931_Div_UserInfo, ASN1_TAG_APPLICATION_WIDE, 0, &DiversionInformation->UserInfo);
|
|
|
|
return p - beg;
|
|
} /* end ParseDiversionInformation() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the CallDeflection facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param CallDeflection Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacCallDeflection(__u8 * Dest, const struct asn1_parm *pc, const struct FacCallDeflection *CallDeflection)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
switch (pc->comp) {
|
|
case CompInvoke:
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_CallDeflection);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeAddress_Full(p, &CallDeflection->Deflection);
|
|
if (CallDeflection->PresentationAllowedToDivertedToUserPresent) {
|
|
p += encodeBoolean(p, ASN1_TAG_BOOLEAN,
|
|
CallDeflection->PresentationAllowedToDivertedToUser);
|
|
}
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
case CompReturnResult:
|
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeOperationValue(p, Fac_CallDeflection);
|
|
|
|
/* No arguments */
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
default:
|
|
Length = -1;
|
|
break;
|
|
} /* end switch */
|
|
|
|
return Length;
|
|
} /* end encodeFacCallDeflection() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the CallDeflection invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param CallDeflection Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseCallDeflection(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCallDeflection *CallDeflection)
|
|
{
|
|
int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseAddress_Full, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &CallDeflection->Deflection);
|
|
|
|
if (p < end) {
|
|
CallDeflection->PresentationAllowedToDivertedToUserPresent = 1;
|
|
XSEQUENCE_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &Value);
|
|
CallDeflection->PresentationAllowedToDivertedToUser = Value;
|
|
} else {
|
|
CallDeflection->PresentationAllowedToDivertedToUserPresent = 0;
|
|
}
|
|
|
|
return p - beg;
|
|
} /* end ParseCallDeflection() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the CallRerouteing facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param CallRerouteing Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacCallRerouteing(__u8 * Dest, const struct asn1_parm *pc, const struct FacCallRerouteing *CallRerouteing)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
__u8 *TagStart;
|
|
__u8 big = 0;
|
|
|
|
start:
|
|
switch (pc->comp) {
|
|
case CompInvoke:
|
|
if (big)
|
|
p = encodeComponentInvoke_Head_Long_u8(Dest, pc->u.inv.invokeId, Fac_CallRerouteing);
|
|
else
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_CallRerouteing);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2 + big];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, CallRerouteing->ReroutingReason);
|
|
p += encodeAddress_Full(p, &CallRerouteing->CalledAddress);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, CallRerouteing->ReroutingCounter);
|
|
p += encodeQ931_Div(p, &CallRerouteing->Q931ie);
|
|
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePresentedNumberUnscreened_Full(p, &CallRerouteing->LastRerouting);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
|
|
if (CallRerouteing->SubscriptionOption) {
|
|
/* Not the DEFAULT value */
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2;
|
|
p = &TagStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, CallRerouteing->SubscriptionOption);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
|
|
if (CallRerouteing->CallingPartySubaddress.Length) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePartySubaddress_Full(p, &CallRerouteing->CallingPartySubaddress);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
|
|
/* sequence Length */
|
|
if (big) {
|
|
encodeLen_Long_u8(&SeqStart[1], p - &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
|
Length = encodeComponent_Length_Long_u8(Dest, p);
|
|
} else {
|
|
Length = p - &SeqStart[2];
|
|
if (Length > 127) {
|
|
big = 1; /* == ASN1_NUM_OCTETS_LONG_LENGTH_u8 - 1 */
|
|
/* start again with full byte length element */
|
|
goto start;
|
|
}
|
|
SeqStart[1] = Length & 0x7f;
|
|
Length = encodeComponent_Length(Dest, p);
|
|
}
|
|
break;
|
|
case CompReturnResult:
|
|
p = encodeComponent_Head(Dest, asn1ComponentTag_Result);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeOperationValue(p, Fac_CallRerouteing);
|
|
|
|
/* No arguments */
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
default:
|
|
Length = -1;
|
|
break;
|
|
} /* end switch */
|
|
|
|
return Length;
|
|
} /* end encodeFacCallRerouteing() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the CallRerouteing invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param CallRerouteing Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseCallRerouteing(struct asn1_parm *pc, u_char * p, u_char * end, struct FacCallRerouteing *CallRerouteing)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
CallRerouteing->ReroutingReason = Value;
|
|
XSEQUENCE_1(ParseAddress_Full, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &CallRerouteing->CalledAddress);
|
|
XSEQUENCE_1(ParseUnsignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &Value);
|
|
CallRerouteing->ReroutingCounter = Value;
|
|
XSEQUENCE_1(ParseQ931_Div, ASN1_TAG_APPLICATION_WIDE, 0, &CallRerouteing->Q931ie);
|
|
XSEQUENCE_1(ParsePresentedNumberUnscreened_Full, ASN1_TAG_CONTEXT_SPECIFIC, ASN1_TAG_EXPLICIT | 1,
|
|
&CallRerouteing->LastRerouting);
|
|
Value = 0; /* DEFAULT value noNotification */
|
|
XSEQUENCE_OPT_1(ParseEnum, ASN1_TAG_CONTEXT_SPECIFIC, ASN1_TAG_EXPLICIT | 2, &Value);
|
|
CallRerouteing->SubscriptionOption = Value;
|
|
CallRerouteing->CallingPartySubaddress.Length = 0;
|
|
XSEQUENCE_OPT_1(ParsePartySubaddress_Full, ASN1_TAG_CONTEXT_SPECIFIC, ASN1_TAG_EXPLICIT | 3,
|
|
&CallRerouteing->CallingPartySubaddress);
|
|
|
|
return p - beg;
|
|
} /* end ParseCallRerouteing() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the InterrogateServedUserNumbers facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param InterrogateServedUserNumbers Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacInterrogateServedUserNumbers(__u8 * Dest, const struct asn1_parm *pc, const struct FacServedUserNumberList *InterrogateServedUserNumbers)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
switch (pc->comp) {
|
|
case CompInvoke:
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_InterrogateServedUserNumbers);
|
|
|
|
/* No arguments */
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
break;
|
|
case CompReturnResult:
|
|
p = encodeComponent_Head_Long_u8(Dest, asn1ComponentTag_Result);
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, pc->u.retResult.invokeId);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8];
|
|
|
|
p += encodeOperationValue(p, Fac_InterrogateServedUserNumbers);
|
|
|
|
p += encodeServedUserNumberList(p, InterrogateServedUserNumbers);
|
|
|
|
/* sequence Length */
|
|
encodeLen_Long_u8(&SeqStart[1], p - &SeqStart[1 + ASN1_NUM_OCTETS_LONG_LENGTH_u8]);
|
|
|
|
Length = encodeComponent_Length_Long_u8(Dest, p);
|
|
break;
|
|
default:
|
|
Length = -1;
|
|
break;
|
|
} /* end switch */
|
|
|
|
return Length;
|
|
} /* end encodeFacInterrogateServedUserNumbers() */
|
|
|
|
/* ******************************************************************* */
|
|
#if 0
|
|
/*!
|
|
* \brief Parse the InterrogateServedUserNumbers result parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse parameters
|
|
* \param end End buffer position that must not go past.
|
|
* \param InterrogateServedUserNumbers Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseInterrogateServedUserNumbers_RES(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacServedUserNumberList *InterrogateServedUserNumbers)
|
|
{
|
|
return ParseServedUserNumberList(pc, p, end, InterrogationDiversion);
|
|
} /* end ParseInterrogateServedUserNumbers_RES() */
|
|
#endif
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the DivertingLegInformation1 facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param DivertingLegInformation1 Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacDivertingLegInformation1(__u8 * Dest, const struct asn1_parm *pc, const struct FacDivertingLegInformation1 *DivertingLegInformation1)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_DivertingLegInformation1);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DivertingLegInformation1->DiversionReason);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DivertingLegInformation1->SubscriptionOption);
|
|
if (DivertingLegInformation1->DivertedToPresent) {
|
|
p += encodePresentedNumberUnscreened_Full(p, &DivertingLegInformation1->DivertedTo);
|
|
}
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
|
|
return Length;
|
|
} /* end encodeFacDivertingLegInformation1() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the DivertingLegInformation1 invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param DivertingLegInformation1 Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseDivertingLegInformation1(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacDivertingLegInformation1 *DivertingLegInformation1)
|
|
{
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DivertingLegInformation1->DiversionReason = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DivertingLegInformation1->SubscriptionOption = Value;
|
|
if (p < end) {
|
|
XSEQUENCE_1(ParsePresentedNumberUnscreened_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED,
|
|
&DivertingLegInformation1->DivertedTo);
|
|
DivertingLegInformation1->DivertedToPresent = 1;
|
|
} else {
|
|
DivertingLegInformation1->DivertedToPresent = 0;
|
|
}
|
|
|
|
return p - beg;
|
|
} /* end ParseDivertingLegInformation1() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the DivertingLegInformation2 facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param DivertingLegInformation2 Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacDivertingLegInformation2(__u8 * Dest, const struct asn1_parm *pc, const struct FacDivertingLegInformation2 *DivertingLegInformation2)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
__u8 *SeqStart;
|
|
__u8 *TagStart;
|
|
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_DivertingLegInformation2);
|
|
|
|
SeqStart = p;
|
|
SeqStart[0] = ASN1_TAG_SEQUENCE;
|
|
p = &SeqStart[2];
|
|
|
|
p += encodeInt(p, ASN1_TAG_INTEGER, DivertingLegInformation2->DiversionCounter);
|
|
p += encodeEnum(p, ASN1_TAG_ENUM, DivertingLegInformation2->DiversionReason);
|
|
|
|
if (DivertingLegInformation2->DivertingPresent) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePresentedNumberUnscreened_Full(p, &DivertingLegInformation2->Diverting);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
|
|
if (DivertingLegInformation2->OriginalCalledPresent) {
|
|
TagStart = p;
|
|
TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2;
|
|
p = &TagStart[2];
|
|
|
|
p += encodePresentedNumberUnscreened_Full(p, &DivertingLegInformation2->OriginalCalled);
|
|
|
|
/* Tag Length */
|
|
TagStart[1] = p - &TagStart[2];
|
|
}
|
|
|
|
/* sequence Length */
|
|
SeqStart[1] = p - &SeqStart[2];
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
|
|
return Length;
|
|
} /* end encodeFacDivertingLegInformation2() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the DivertingLegInformation2 invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param DivertingLegInformation2 Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseDivertingLegInformation2(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacDivertingLegInformation2 *DivertingLegInformation2)
|
|
{
|
|
int xtag;
|
|
int xlen;
|
|
unsigned int Value;
|
|
INIT;
|
|
|
|
XSEQUENCE_1(ParseUnsignedInteger, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &Value);
|
|
DivertingLegInformation2->DiversionCounter = Value;
|
|
XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &Value);
|
|
DivertingLegInformation2->DiversionReason = Value;
|
|
|
|
if (p < end && *p == (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1)) {
|
|
DivertingLegInformation2->DivertingPresent = 1;
|
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag));
|
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen));
|
|
CallASN1(ret, p, end, ParsePresentedNumberUnscreened_Full(pc, p, end, &DivertingLegInformation2->Diverting));
|
|
} else {
|
|
DivertingLegInformation2->DivertingPresent = 0;
|
|
}
|
|
|
|
if (p < end && *p == (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2)) {
|
|
DivertingLegInformation2->OriginalCalledPresent = 1;
|
|
CallASN1(ret, p, end, ParseTag(p, end, &xtag));
|
|
CallASN1(ret, p, end, ParseLen(p, end, &xlen));
|
|
CallASN1(ret, p, end, ParsePresentedNumberUnscreened_Full(pc, p, end, &DivertingLegInformation2->OriginalCalled));
|
|
} else {
|
|
DivertingLegInformation2->OriginalCalledPresent = 0;
|
|
}
|
|
|
|
return p - beg;
|
|
} /* end ParseDivertingLegInformation2() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Encode the DivertingLegInformation3 facility ie.
|
|
*
|
|
* \param Dest Where to put the encoding
|
|
* \param DivertingLegInformation3 Information needed to encode in ie.
|
|
*
|
|
* \retval length on success.
|
|
* \retval -1 on error.
|
|
*/
|
|
int encodeFacDivertingLegInformation3(__u8 * Dest, const struct asn1_parm *pc, const struct FacDivertingLegInformation3 *DivertingLegInformation3)
|
|
{
|
|
int Length;
|
|
__u8 *p;
|
|
|
|
p = encodeComponentInvoke_Head(Dest, pc->u.inv.invokeId, Fac_DivertingLegInformation3);
|
|
|
|
p += encodeBoolean(p, ASN1_TAG_BOOLEAN, DivertingLegInformation3->PresentationAllowedIndicator);
|
|
|
|
Length = encodeComponent_Length(Dest, p);
|
|
|
|
return Length;
|
|
} /* end encodeFacDivertingLegInformation3() */
|
|
|
|
/* ******************************************************************* */
|
|
/*!
|
|
* \brief Parse the DivertingLegInformation3 invoke argument parameters.
|
|
*
|
|
* \param pc Complete component message storage data.
|
|
* \param p Starting buffer position to parse arguments
|
|
* \param end End buffer position that must not go past.
|
|
* \param DivertingLegInformation3 Parameter storage to fill.
|
|
*
|
|
* \retval length of buffer consumed
|
|
* \retval -1 on error.
|
|
*/
|
|
int ParseDivertingLegInformation3(struct asn1_parm *pc, u_char * p, u_char * end,
|
|
struct FacDivertingLegInformation3 *DivertingLegInformation3)
|
|
{
|
|
int Value;
|
|
int ret;
|
|
u_char *beg;
|
|
|
|
beg = p;
|
|
|
|
XSEQUENCE_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &Value);
|
|
DivertingLegInformation3->PresentationAllowedIndicator = Value;
|
|
|
|
return p - beg;
|
|
} /* end ParseDivertingLegInformation3() */
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
/* end asn1_diversion.c */
|