[thirdparty-commits] rmudgett: mISDNuser/trunk r29 - /mISDNuser/trunk/suppserv/
SVN commits to the Digium third-party software repository
thirdparty-commits at lists.digium.com
Wed Nov 12 10:48:55 CST 2008
Author: rmudgett
Date: Wed Nov 12 10:48:55 2008
New Revision: 29
URL: http://svn.digium.com/view/thirdparty?view=rev&rev=29
Log:
Moved functions and prototypes to the files they should be in
Modified:
mISDNuser/trunk/suppserv/asn1.h
mISDNuser/trunk/suppserv/asn1_address.c
mISDNuser/trunk/suppserv/asn1_ccbs.c
mISDNuser/trunk/suppserv/asn1_comp.c
mISDNuser/trunk/suppserv/asn1_diversion.c
mISDNuser/trunk/suppserv/asn1_diversion.h
mISDNuser/trunk/suppserv/asn1_ect.c
mISDNuser/trunk/suppserv/asn1_enc.c
mISDNuser/trunk/suppserv/fac.c
Modified: mISDNuser/trunk/suppserv/asn1.h
URL: http://svn.digium.com/view/thirdparty/mISDNuser/trunk/suppserv/asn1.h?view=diff&rev=29&r1=28&r2=29
==============================================================================
--- mISDNuser/trunk/suppserv/asn1.h (original)
+++ mISDNuser/trunk/suppserv/asn1.h Wed Nov 12 10:48:55 2008
@@ -1,5 +1,7 @@
#ifndef __ASN1_H__
#define __ASN1_H__
+
+#define ASN1_DEBUG 1 /* BUGBUG Debug messages turned on */
#include "suppserv.h"
#include <asm/types.h>
@@ -334,6 +336,7 @@
return -1; \
} while (0)
+
const struct asn1OidConvert *FindOidByOidValue(int length, const __u16 oidValues[]);
const struct asn1OidConvert *FindOidByEnum(__u16 value);
__u16 ConvertOidToEnum(const struct asn1Oid *oid, __u16 errorValue);
@@ -342,6 +345,11 @@
((FAC_OID_BASE(1) <= (enumValue) \
&& (enumValue) < FAC_OID_BASE(FacOIDBase_Last)) ? 1 : 0)
+/*
+** ASN.1 Encoding
+*/
+
+/* Facility-Information-Element-Components prototypes */
enum asn1ComponentTag {
asn1ComponentTag_Invoke = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 1,
asn1ComponentTag_Result = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 2,
@@ -358,10 +366,7 @@
int encodeOperationValue(__u8 *dest, int operationValue);
int encodeErrorValue(__u8 *dest, int errorValue);
-/*
-** ASN.1 Encoding
-*/
-
+/* Primitive ASN.1 prototypes */
#define ASN1_NUM_OCTETS_LONG_LENGTH_u8 2
#define ASN1_NUM_OCTETS_LONG_LENGTH_u16 3
int encodeLen_Long_u8(__u8 *dest, __u8 length);
@@ -377,55 +382,44 @@
int encodeIA5String(__u8 *dest, __u8 tagType, const __s8 *str, __u8 len);
int encodeOid(__u8 *dest, __u8 tagType, const struct asn1Oid *oid);
+/* Addressing-Data-Elements prototypes */
int encodePartyNumber_Full(__u8 *Dest, const struct FacPartyNumber *PartyNumber);
int encodePartySubaddress_Full(__u8 *Dest, const struct FacPartySubaddress *PartySubaddress);
int encodeAddress_Full(__u8 *Dest, const struct FacAddress *Address);
int encodePresentedNumberUnscreened_Full(__u8 *Dest, const struct FacPresentedNumberUnscreened *Presented);
-
int encodePublicPartyNumber(__u8 *dest, __s8 *facilityPartyNumber);
int encodePartyNumber(__u8 *dest, __s8 *facilityPartyNumber);
-int encodeServedUserNumber(__u8 *dest, __s8 *servedUserNumber);
int encodeAddress(__u8 *dest, __s8 *facilityPartyNumber, __s8 *calledPartySubaddress);
/*
** ASN.1 Parsing
*/
+
+/* Facility-Information-Element-Components prototypes */
+int ParseComponent(struct asn1_parm *parm, u_char *p, u_char *end);
+
+/* Primitive ASN.1 prototypes */
+int ParseBoolean(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
+int ParseNull(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
+int ParseInteger(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
+int ParseEnum(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
struct asn1ParseString {
char *buf; /* Where to put the parsed string characters */
size_t maxSize; /* sizeof string buffer (Including an ASCIIz terminator) */
size_t length; /* length of string put into the string buffer (Without the terminator) */
};
-int ParseBoolean(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
-int ParseNull(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
-int ParseInteger(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
-int ParseEnum(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
int ParseIA5String(struct asn1_parm *pc, u_char *p, u_char *end, struct asn1ParseString *str);
int ParseNumericString(struct asn1_parm *pc, u_char *p, u_char *end, struct asn1ParseString *str);
int ParseOctetString(struct asn1_parm *pc, u_char *p, u_char *end, struct asn1ParseString *str);
int ParseOid(struct asn1_parm *pc, u_char *p, u_char *end, struct asn1Oid *oid);
+/* Addressing-Data-Elements prototypes */
int ParsePartyNumber_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber);
int ParsePartySubaddress_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress);
int ParseAddress_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacAddress *Address);
int ParsePresentedNumberUnscreened_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPresentedNumberUnscreened *Presented);
-
-
-int ParseARGReqCallDeflection(struct asn1_parm *pc, u_char *p, u_char *end, struct ReqCallDeflection *reqCD);
-int ParseARGActivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct ActDivNotification *actNot);
-int ParseARGDeactivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct DeactDivNotification *deactNot);
-int ParseARGInterrogationDiversion(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
-int ParseRESInterrogationDiversion(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
-int ParseARGInterrogateServedUserNumbers(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
-int ParseRESInterrogateServedUserNumbers(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
-int ParseARGDiversionInformation(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
-int ParseIntResult(struct asn1_parm *parm, u_char *p, u_char *end, struct IntResult *intResult);
-int ParseIntResultList(struct asn1_parm *parm, u_char *p, u_char *end, struct IntResultList *intResultList);
-int ParseServedUserNr(struct asn1_parm *parm, u_char *p, u_char *end, struct ServedUserNr *servedUserNr);
-int ParseProcedure(struct asn1_parm *pc, u_char *p, u_char *end, int *procedure);
-int ParseServedUserNumberList(struct asn1_parm *parm, u_char *p, u_char *end, struct ServedUserNumberList *list);
-int ParseDiversionReason(struct asn1_parm *parm, u_char *p, u_char *end, char *str);
int ParsePresentedAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
int ParsePresentedNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
@@ -443,12 +437,8 @@
int ParseNSAPSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
int ParseSubaddressInformation(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
int ParseScreeningIndicator(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
-int ParseNumberDigits(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
-
-int ParseReturnResultComponent(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
-int ParseComponent(struct asn1_parm *parm, u_char *p, u_char *end);
-int XParseComponent(struct asn1_parm *parm, u_char *p, u_char *end);
-
+
+/* Advice Of Charge (AOC) prototypes */
int ParseAOCECurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
int ParseAOCDChargingUnit(struct asn1_parm *pc,u_char *p, u_char *end, struct FacAOCDChargingUnit *chu);
int ParseAOCDCurrency(struct asn1_parm *pc, u_char *p, u_char *end, struct FacAOCDCurrency *cur);
@@ -471,6 +461,7 @@
int ParseChargingAssociation(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
int ParseChargeIdentifier(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
+/* Basic-Service-Elements prototypes */
int ParseBasicService(struct asn1_parm *pc, u_char *p, u_char *end, int *basicService);
#endif
Modified: mISDNuser/trunk/suppserv/asn1_address.c
URL: http://svn.digium.com/view/thirdparty/mISDNuser/trunk/suppserv/asn1_address.c?view=diff&rev=29&r1=28&r2=29
==============================================================================
--- mISDNuser/trunk/suppserv/asn1_address.c (original)
+++ mISDNuser/trunk/suppserv/asn1_address.c Wed Nov 12 10:48:55 2008
@@ -3,16 +3,21 @@
*/
#include "asn1.h"
-#include <stdio.h>
#include <string.h>
-void buildnumber(char *num, int oc3, int oc3a, char *result, int version,
- int *provider, int *sondernummer, int *intern, int *local,
- int dir, int who);
// ======================================================================
// Address Types EN 300 196-1 D.3
+
+static int ParseNumberDigits(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
+{
+ struct asn1ParseString number;
+
+ number.buf = str;
+ number.maxSize = 30;/* sizeof(struct partyNumber.p.unknown) and sizeof(struct publicPartyNumber.numberDigits) */
+ return ParseNumericString(pc, p, end, &number);
+}
int ParsePresentationRestricted(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
{
@@ -235,11 +240,573 @@
return ret;
}
-int ParseNumberDigits(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
-{
- struct asn1ParseString number;
-
- number.buf = str;
- number.maxSize = 30;/* sizeof(struct partyNumber.p.unknown) and sizeof(struct publicPartyNumber.numberDigits) */
- return ParseNumericString(pc, p, end, &number);
-}
+
+
+
+int encodePublicPartyNumber(__u8 *dest, __s8 *facilityPartyNumber)
+{
+ __u8 *p;
+
+ dest[0] = ASN1_TAG_SEQUENCE;
+
+ /* Store value */
+ p = &dest[2];
+ p += encodeEnum(p, ASN1_TAG_ENUM, (facilityPartyNumber[2] & 0x70) >> 4);
+ p += encodeNumericString(p, ASN1_TAG_NUMERIC_STRING, &facilityPartyNumber[4], facilityPartyNumber[0] - 3);
+
+ /* length */
+ dest[1] = p - &dest[2];
+
+ return p - dest;
+}
+
+int encodePartyNumber(__u8 *dest, __s8 *facilityPartyNumber)
+{
+ __u8 *p = dest;
+
+ p += encodeNumericString(p, ASN1_TAG_CONTEXT_SPECIFIC | 0, facilityPartyNumber, strlen((char *)facilityPartyNumber));
+#if 0
+ switch (facilityPartyNumber[1]) {
+ case 0: // unknown
+ p += encodeNumericString(p, ASN1_TAG_CONTEXT_SPECIFIC | 1, &facilityPartyNumber[4], facilityPartyNumber[0] - 3);
+ break;
+ case 1: // publicPartyNumber
+ p += encodePublicPartyNumber(p, facilityPartyNumber);
+ dest[0] &= ASN1_TAG_CONSTRUCTED; /* Keep constructed flag */
+ dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 1;
+ break;
+ default:
+ int_error();
+ return -1;
+ }
+#endif
+ return p - dest;
+}
+
+int encodeAddress(__u8 *dest, __s8 *facilityPartyNumber, __s8 *calledPartySubaddress)
+{
+ __u8 *p = dest;
+
+ dest[0] = ASN1_TAG_SEQUENCE;
+
+ /* Store value */
+ p = &dest[2];
+ p += encodePartyNumber(p, facilityPartyNumber);
+#if 0 // FIXME
+ if (calledPartySubaddress[0])
+ p += encodePartySubaddress(p, calledPartySubaddress);
+#endif
+
+ /* length */
+ dest[1] = p - &dest[2];
+
+ return p - dest;
+}
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Parse the NumberDigits PartyNumber 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 PartyNumber Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+static int ParseNumberDigits_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
+{
+ struct asn1ParseString Number;
+ int LengthConsumed;
+
+ Number.buf = (char *) PartyNumber->Number;
+ Number.maxSize = sizeof(PartyNumber->Number);
+ Number.length = 0;
+ LengthConsumed = ParseNumericString(pc, p, end, &Number);
+ PartyNumber->LengthOfNumber = Number.length;
+ return LengthConsumed;
+} /* end ParseNumberDigits_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Parse the NSAP PartyNumber 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 PartyNumber Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+static int ParseNSAPPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
+{
+ struct asn1ParseString Number;
+ int LengthConsumed;
+
+ Number.buf = (char *) PartyNumber->Number;
+ Number.maxSize = sizeof(PartyNumber->Number);
+ Number.length = 0;
+ LengthConsumed = ParseOctetString(pc, p, end, &Number);
+ PartyNumber->LengthOfNumber = Number.length;
+ return LengthConsumed;
+} /* end ParseNSAPPartyNumber() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Encode the public or private network PartyNumber type.
+ *
+ * \param Dest Where to put the encoding
+ * \param Number
+ * \param LengthOfNumber
+ * \param TypeOfNumber
+ *
+ * \retval length
+ */
+static int encodeNetworkPartyNumber(__u8 *Dest, const __s8 *Number, __u8 LengthOfNumber, __u8 TypeOfNumber)
+{
+ __u8 *p;
+
+ Dest[0] = ASN1_TAG_SEQUENCE;
+ p = &Dest[2];
+ p += encodeEnum(p, ASN1_TAG_ENUM, TypeOfNumber);
+ p += encodeNumericString(p, ASN1_TAG_NUMERIC_STRING, Number, LengthOfNumber);
+
+ /* length */
+ Dest[1] = p - &Dest[2];
+
+ return p - Dest;
+} /* end encodeNetworkPartyNumber() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Parse the public or private network PartyNumber 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 PartyNumber Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+static int ParseNetworkPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
+{
+ int TypeOfNumber;
+ INIT;
+
+ XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &TypeOfNumber);
+ PartyNumber->TypeOfNumber = TypeOfNumber;
+ XSEQUENCE_1(ParseNumberDigits_Full, ASN1_TAG_NUMERIC_STRING, ASN1_NOT_TAGGED, PartyNumber);
+
+ return p - beg;
+} /* end ParseNetworkPartyNumber() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Encode the PartyNumber type.
+ *
+ * \param Dest Where to put the encoding
+ * \param PartyNumber Number information to encode.
+ *
+ * \retval length
+ */
+int encodePartyNumber_Full(__u8 *Dest, const struct FacPartyNumber *PartyNumber)
+{
+ int Length;
+
+ switch (PartyNumber->Type) {
+ case 0: /* Unknown PartyNumber */
+ Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 0, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
+ break;
+ case 1: /* Public PartyNumber */
+ Length = encodeNetworkPartyNumber(Dest, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber, PartyNumber->TypeOfNumber);
+ Dest[0] &= ASN1_TAG_CONSTRUCTED;
+ Dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 1;
+ break;
+ case 2: /* NSAP encoded PartyNumber */
+ Length = encodeOctetString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 2, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
+ break;
+ case 3: /* Data PartyNumber (Not used) */
+ Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 3, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
+ break;
+ case 4: /* Telex PartyNumber (Not used) */
+ Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 4, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
+ break;
+ case 5: /* Private PartyNumber */
+ Length = encodeNetworkPartyNumber(Dest, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber, PartyNumber->TypeOfNumber);
+ Dest[0] &= ASN1_TAG_CONSTRUCTED;
+ Dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 5;
+ break;
+ case 8: /* National Standard PartyNumber (Not used) */
+ Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 8, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
+ break;
+ default:
+ Length = 0;
+ break;
+ } /* end switch */
+
+ return Length;
+} /* end encodePartyNumber_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Parse the PartyNumber 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 PartyNumber Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+int ParsePartyNumber_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
+{
+ INIT;
+
+ PartyNumber->Type = 0;/* Unknown PartyNumber */
+ XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 0, PartyNumber);
+ PartyNumber->Type = 1;/* Public PartyNumber */
+ XCHOICE_1(ParseNetworkPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, PartyNumber);
+ PartyNumber->Type = 2;/* NSAP encoded PartyNumber */
+ XCHOICE_1(ParseNSAPPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC, 2, PartyNumber);
+ PartyNumber->Type = 3;/* Data PartyNumber (Not used) */
+ XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 3, PartyNumber);
+ PartyNumber->Type = 4;/* Telex PartyNumber (Not used) */
+ XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 4, PartyNumber);
+ PartyNumber->Type = 5;/* Private PartyNumber */
+ XCHOICE_1(ParseNetworkPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 5, PartyNumber);
+ PartyNumber->Type = 8;/* National Standard PartyNumber (Not used) */
+ XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 8, PartyNumber);
+
+ XCHOICE_DEFAULT;
+} /* end ParsePartyNumber_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Parse the User information string PartySubaddress 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 PartySubaddress Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+static int ParseUserSubaddressInfo(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
+{
+ struct asn1ParseString Subaddress;
+ int LengthConsumed;
+
+ Subaddress.buf = (char *) PartySubaddress->u.UserSpecified.Information;
+ Subaddress.maxSize = sizeof(PartySubaddress->u.UserSpecified.Information);
+ Subaddress.length = 0;
+ LengthConsumed = ParseOctetString(pc, p, end, &Subaddress);
+ PartySubaddress->Length = Subaddress.length;
+ return LengthConsumed;
+} /* end ParseUserSubaddressInfo() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Parse the User PartySubaddress 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 PartySubaddress Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+static int ParseUserSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
+{
+ int OddCount;
+ INIT;
+
+ PartySubaddress->Type = 0;/* UserSpecified */
+
+ XSEQUENCE_1(ParseUserSubaddressInfo, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, PartySubaddress);
+ if (p < end) {
+ XSEQUENCE_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &OddCount);
+ PartySubaddress->u.UserSpecified.OddCount = OddCount;
+ PartySubaddress->u.UserSpecified.OddCountPresent = 1;
+ } else {
+ PartySubaddress->u.UserSpecified.OddCount = 0;
+ PartySubaddress->u.UserSpecified.OddCountPresent = 0;
+ }
+ return p - beg;
+} /* end ParseUserSubaddress() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \internal
+ * \brief Parse the NSAP PartySubaddress 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 PartySubaddress Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+static int ParseNSAPSubaddress_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
+{
+ struct asn1ParseString Subaddress;
+ int LengthConsumed;
+
+ PartySubaddress->Type = 1;/* NSAP */
+
+ Subaddress.buf = (char *) PartySubaddress->u.Nsap;
+ Subaddress.maxSize = sizeof(PartySubaddress->u.Nsap);
+ Subaddress.length = 0;
+ LengthConsumed = ParseOctetString(pc, p, end, &Subaddress);
+ PartySubaddress->Length = Subaddress.length;
+ return LengthConsumed;
+} /* end ParseNSAPSubaddress_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Encode the PartySubaddress type.
+ *
+ * \param Dest Where to put the encoding
+ * \param PartySubaddress Subaddress information to encode.
+ *
+ * \retval length
+ */
+int encodePartySubaddress_Full(__u8 *Dest, const struct FacPartySubaddress *PartySubaddress)
+{
+ __u8 *p;
+ int Length;
+
+ switch (PartySubaddress->Type) {
+ case 0: /* UserSpecified */
+ Dest[0] = ASN1_TAG_SEQUENCE;
+ p = &Dest[2];
+ p += encodeOctetString(p, ASN1_TAG_OCTET_STRING, (const __s8 *) PartySubaddress->u.UserSpecified.Information, PartySubaddress->Length);
+ if (PartySubaddress->u.UserSpecified.OddCountPresent) {
+ p += encodeBoolean(p, ASN1_TAG_BOOLEAN, PartySubaddress->u.UserSpecified.OddCount);
+ }
+
+ /* length */
+ Dest[1] = p - &Dest[2];
+
+ Length = p - Dest;
+ break;
+ case 1: /* NSAP */
+ Length = encodeOctetString(Dest, ASN1_TAG_OCTET_STRING, (const __s8 *) PartySubaddress->u.Nsap, PartySubaddress->Length);
+ break;
+ default:
+ Length = 0;
+ break;
+ } /* end switch */
+
+ return Length;
+} /* end encodePartySubaddress_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Parse the PartySubaddress 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 PartySubaddress Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+int ParsePartySubaddress_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
+{
+ INIT;
+
+ XCHOICE_1(ParseUserSubaddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, PartySubaddress);
+ XCHOICE_1(ParseNSAPSubaddress_Full, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, PartySubaddress);
+
+ XCHOICE_DEFAULT;
+} /* end ParsePartySubaddress_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Encode the Address type.
+ *
+ * \param Dest Where to put the encoding
+ * \param Address Address information to encode.
+ *
+ * \retval length
+ */
+int encodeAddress_Full(__u8 *Dest, const struct FacAddress *Address)
+{
+ __u8 *p;
+
+ Dest[0] = ASN1_TAG_SEQUENCE;
+ p = &Dest[2];
+ p += encodePartyNumber_Full(p, &Address->Party);
+ if (Address->Subaddress.Length) {
+ p += encodePartySubaddress_Full(p, &Address->Subaddress);
+ }
+
+ /* length */
+ Dest[1] = p - &Dest[2];
+
+ return p - Dest;
+} /* end encodeAddress_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Parse the Address 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 Address Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+int ParseAddress_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacAddress *Address)
+{
+ INIT;
+
+ XSEQUENCE_1(ParsePartyNumber_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &Address->Party);
+ if (p < end) {
+ /* The optional subaddress must be present since there is something left. */
+ XSEQUENCE_1(ParsePartySubaddress_Full, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &Address->Subaddress);
+ } else {
+ Address->Subaddress.Length = 0;/* Subaddress not present */
+ }
+
+ return p - beg;
+} /* end ParseAddress_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Encode the PresentedNumberUnscreened type.
+ *
+ * \param Dest Where to put the encoding
+ * \param Presented Number information to encode.
+ *
+ * \retval length
+ */
+int encodePresentedNumberUnscreened_Full(__u8 *Dest, const struct FacPresentedNumberUnscreened *Presented)
+{
+ __u8 *p;
+ __u8 *TagStart;
+
+ p = Dest;
+ switch (Presented->Type) {
+ case 0: /* presentationAllowedNumber */
+ TagStart = p;
+ TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 0;
+ p = &TagStart[2];
+
+ p += encodePartyNumber_Full(p, &Presented->Unscreened);
+
+ /* tag Length */
+ TagStart[1] = p - &TagStart[2];
+ break;
+ case 1: /* presentationRestricted */
+ p += encodeNull(p, ASN1_TAG_CONTEXT_SPECIFIC | 1);
+ break;
+ case 2: /* numberNotAvailableDueToInterworking */
+ p += encodeNull(p, ASN1_TAG_CONTEXT_SPECIFIC | 2);
+ break;
+ case 3: /* presentationRestrictedNumber */
+ TagStart = p;
+ TagStart[0] = ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED | 3;
+ p = &TagStart[2];
+
+ p += encodePartyNumber_Full(p, &Presented->Unscreened);
+
+ /* tag Length */
+ TagStart[1] = p - &TagStart[2];
+ break;
+ default:
+ break;
+ } /* end switch */
+
+ return p - Dest;
+} /* end encodePresentedNumberUnscreened_Full() */
+
+
+
+
+/* ******************************************************************* */
+/*!
+ * \brief Parse the PresentedNumberUnscreened 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 Presented Parameter storage to fill.
+ *
+ * \retval length of buffer consumed
+ * \retval -1 on error.
+ */
+int ParsePresentedNumberUnscreened_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPresentedNumberUnscreened *Presented)
+{
+ INIT;
+
+ Presented->Type = 0;
+ XCHOICE_1(ParsePartyNumber_Full, ASN1_TAG_EXPLICIT | ASN1_TAG_CONTEXT_SPECIFIC, 0, &Presented->Unscreened);
+ Presented->Type = 1;
+ XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 1);
+ Presented->Type = 2;
+ XCHOICE(ParseNull, ASN1_TAG_CONTEXT_SPECIFIC, 2);
+ Presented->Type = 3;
+ XCHOICE_1(ParsePartyNumber_Full, ASN1_TAG_EXPLICIT | ASN1_TAG_CONTEXT_SPECIFIC, 3, &Presented->Unscreened);
+
+ XCHOICE_DEFAULT;
+} /* end ParsePresentedNumberUnscreened_Full() */
+
Modified: mISDNuser/trunk/suppserv/asn1_ccbs.c
URL: http://svn.digium.com/view/thirdparty/mISDNuser/trunk/suppserv/asn1_ccbs.c?view=diff&rev=29&r1=28&r2=29
==============================================================================
--- mISDNuser/trunk/suppserv/asn1_ccbs.c (original)
+++ mISDNuser/trunk/suppserv/asn1_ccbs.c Wed Nov 12 10:48:55 2008
@@ -9,8 +9,6 @@
#include "asn1.h"
#include "asn1_ccbs.h"
-#include "l3dss1.h"
-#include <stdio.h>
#include <string.h>
/* ------------------------------------------------------------------- */
@@ -28,7 +26,7 @@
*
* \retval length
*/
-static int encodeQ931ie(__u8 *Dest, const struct Q931_Bc_Hlc_Llc *Q931ie)
+static int encodeQ931ie_CCBS(__u8 *Dest, const struct Q931_Bc_Hlc_Llc *Q931ie)
{
__u8 *p;
@@ -60,7 +58,7 @@
Dest[1] = p - &Dest[2];
return p - Dest;
-} /* end encodeQ931ie() */
+} /* end encodeQ931ie_CCBS() */
@@ -68,7 +66,7 @@
/* ******************************************************************* */
/*!
* \internal
- * \brief Parse the Q.931 argument contents.
+ * \brief Parse the Q.931 argument contents for CCBS/CCNR.
*
* \param pc Complete component message storage data.
* \param p Starting buffer position to parse arguments
@@ -78,7 +76,7 @@
* \retval length of buffer consumed
* \retval -1 on error.
*/
-static int ParseQ931ie(struct asn1_parm *pc, u_char *p, u_char *end, struct Q931_Bc_Hlc_Llc *Q931ie)
+static int ParseQ931ie_CCBS(struct asn1_parm *pc, u_char *p, u_char *end, struct Q931_Bc_Hlc_Llc *Q931ie)
{
__u8 Ie_type;
size_t Length;
@@ -123,431 +121,7 @@
} while (p < end);
return p - beg;
-} /* end ParseQ931ie() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Parse the NumberDigits PartyNumber 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 PartyNumber Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-static int ParseNumberDigits_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
-{
- struct asn1ParseString Number;
- int LengthConsumed;
-
- Number.buf = (char *) PartyNumber->Number;
- Number.maxSize = sizeof(PartyNumber->Number);
- Number.length = 0;
- LengthConsumed = ParseNumericString(pc, p, end, &Number);
- PartyNumber->LengthOfNumber = Number.length;
- return LengthConsumed;
-} /* end ParseNumberDigits_Full() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Parse the NSAP PartyNumber 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 PartyNumber Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-static int ParseNSAPPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
-{
- struct asn1ParseString Number;
- int LengthConsumed;
-
- Number.buf = (char *) PartyNumber->Number;
- Number.maxSize = sizeof(PartyNumber->Number);
- Number.length = 0;
- LengthConsumed = ParseOctetString(pc, p, end, &Number);
- PartyNumber->LengthOfNumber = Number.length;
- return LengthConsumed;
-} /* end ParseNSAPPartyNumber() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Encode the public or private network PartyNumber type.
- *
- * \param Dest Where to put the encoding
- * \param Number
- * \param LengthOfNumber
- * \param TypeOfNumber
- *
- * \retval length
- */
-static int encodeNetworkPartyNumber(__u8 *Dest, const __s8 *Number, __u8 LengthOfNumber, __u8 TypeOfNumber)
-{
- __u8 *p;
-
- Dest[0] = ASN1_TAG_SEQUENCE;
- p = &Dest[2];
- p += encodeEnum(p, ASN1_TAG_ENUM, TypeOfNumber);
- p += encodeNumericString(p, ASN1_TAG_NUMERIC_STRING, Number, LengthOfNumber);
-
- /* length */
- Dest[1] = p - &Dest[2];
-
- return p - Dest;
-} /* end encodeNetworkPartyNumber() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Parse the public or private network PartyNumber 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 PartyNumber Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-static int ParseNetworkPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
-{
- int TypeOfNumber;
- INIT;
-
- XSEQUENCE_1(ParseEnum, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &TypeOfNumber);
- PartyNumber->TypeOfNumber = TypeOfNumber;
- XSEQUENCE_1(ParseNumberDigits_Full, ASN1_TAG_NUMERIC_STRING, ASN1_NOT_TAGGED, PartyNumber);
-
- return p - beg;
-} /* end ParseNetworkPartyNumber() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \brief Encode the PartyNumber type.
- *
- * \param Dest Where to put the encoding
- * \param PartyNumber Number information to encode.
- *
- * \retval length
- */
-int encodePartyNumber_Full(__u8 *Dest, const struct FacPartyNumber *PartyNumber)
-{
- int Length;
-
- switch (PartyNumber->Type) {
- case 0: /* Unknown PartyNumber */
- Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 0, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
- break;
- case 1: /* Public PartyNumber */
- Length = encodeNetworkPartyNumber(Dest, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber, PartyNumber->TypeOfNumber);
- Dest[0] &= ASN1_TAG_CONSTRUCTED;
- Dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 1;
- break;
- case 2: /* NSAP encoded PartyNumber */
- Length = encodeOctetString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 2, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
- break;
- case 3: /* Data PartyNumber (Not used) */
- Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 3, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
- break;
- case 4: /* Telex PartyNumber (Not used) */
- Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 4, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
- break;
- case 5: /* Private PartyNumber */
- Length = encodeNetworkPartyNumber(Dest, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber, PartyNumber->TypeOfNumber);
- Dest[0] &= ASN1_TAG_CONSTRUCTED;
- Dest[0] |= ASN1_TAG_CONTEXT_SPECIFIC | 5;
- break;
- case 8: /* National Standard PartyNumber (Not used) */
- Length = encodeNumericString(Dest, ASN1_TAG_CONTEXT_SPECIFIC | 8, (const __s8 *) PartyNumber->Number, PartyNumber->LengthOfNumber);
- break;
- default:
- Length = 0;
- break;
- } /* end switch */
-
- return Length;
-} /* end encodePartyNumber_Full() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \brief Parse the PartyNumber 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 PartyNumber Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-int ParsePartyNumber_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartyNumber *PartyNumber)
-{
- INIT;
-
- PartyNumber->Type = 0;/* Unknown PartyNumber */
- XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 0, PartyNumber);
- PartyNumber->Type = 1;/* Public PartyNumber */
- XCHOICE_1(ParseNetworkPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 1, PartyNumber);
- PartyNumber->Type = 2;/* NSAP encoded PartyNumber */
- XCHOICE_1(ParseNSAPPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC, 2, PartyNumber);
- PartyNumber->Type = 3;/* Data PartyNumber (Not used) */
- XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 3, PartyNumber);
- PartyNumber->Type = 4;/* Telex PartyNumber (Not used) */
- XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 4, PartyNumber);
- PartyNumber->Type = 5;/* Private PartyNumber */
- XCHOICE_1(ParseNetworkPartyNumber, ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED, 5, PartyNumber);
- PartyNumber->Type = 8;/* National Standard PartyNumber (Not used) */
- XCHOICE_1(ParseNumberDigits_Full, ASN1_TAG_CONTEXT_SPECIFIC, 8, PartyNumber);
-
- XCHOICE_DEFAULT;
-} /* end ParsePartyNumber_Full() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Parse the User information string PartySubaddress 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 PartySubaddress Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-static int ParseUserSubaddressInfo(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
-{
- struct asn1ParseString Subaddress;
- int LengthConsumed;
-
- Subaddress.buf = (char *) PartySubaddress->u.UserSpecified.Information;
- Subaddress.maxSize = sizeof(PartySubaddress->u.UserSpecified.Information);
- Subaddress.length = 0;
- LengthConsumed = ParseOctetString(pc, p, end, &Subaddress);
- PartySubaddress->Length = Subaddress.length;
- return LengthConsumed;
-} /* end ParseUserSubaddressInfo() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Parse the User PartySubaddress 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 PartySubaddress Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-static int ParseUserSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
-{
- int OddCount;
- INIT;
-
- PartySubaddress->Type = 0;/* UserSpecified */
-
- XSEQUENCE_1(ParseUserSubaddressInfo, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, PartySubaddress);
- if (p < end) {
- XSEQUENCE_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &OddCount);
- PartySubaddress->u.UserSpecified.OddCount = OddCount;
- PartySubaddress->u.UserSpecified.OddCountPresent = 1;
- } else {
- PartySubaddress->u.UserSpecified.OddCount = 0;
- PartySubaddress->u.UserSpecified.OddCountPresent = 0;
- }
- return p - beg;
-} /* end ParseUserSubaddress() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Parse the NSAP PartySubaddress 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 PartySubaddress Parameter storage to fill.
- *
- * \retval length of buffer consumed
- * \retval -1 on error.
- */
-static int ParseNSAPSubaddress_Full(struct asn1_parm *pc, u_char *p, u_char *end, struct FacPartySubaddress *PartySubaddress)
-{
- struct asn1ParseString Subaddress;
- int LengthConsumed;
-
- PartySubaddress->Type = 1;/* NSAP */
-
- Subaddress.buf = (char *) PartySubaddress->u.Nsap;
- Subaddress.maxSize = sizeof(PartySubaddress->u.Nsap);
- Subaddress.length = 0;
- LengthConsumed = ParseOctetString(pc, p, end, &Subaddress);
- PartySubaddress->Length = Subaddress.length;
- return LengthConsumed;
-} /* end ParseNSAPSubaddress_Full() */
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \brief Encode the PartySubaddress type.
- *
- * \param Dest Where to put the encoding
- * \param PartySubaddress Subaddress information to encode.
- *
- * \retval length
- */
-int encodePartySubaddress_Full(__u8 *Dest, const struct FacPartySubaddress *PartySubaddress)
-{
- __u8 *p;
- int Length;
-
- switch (PartySubaddress->Type) {
- case 0: /* UserSpecified */
- Dest[0] = ASN1_TAG_SEQUENCE;
- p = &Dest[2];
- p += encodeOctetString(p, ASN1_TAG_OCTET_STRING, (const __s8 *) PartySubaddress->u.UserSpecified.Information, PartySubaddress->Length);
- if (PartySubaddress->u.UserSpecified.OddCountPresent) {
- p += encodeBoolean(p, ASN1_TAG_BOOLEAN, PartySubaddress->u.UserSpecified.OddCount);
- }
-
- /* length */
- Dest[1] = p - &Dest[2];
-
- Length = p - Dest;
- break;
- case 1: /* NSAP */
- Length = encodeOctetString(Dest, ASN1_TAG_OCTET_STRING, (const __s8 *) PartySubaddress->u.Nsap, PartySubaddress->Length);
- break;
- default:
- Length = 0;
- break;
- } /* end switch */
-
- return Length;
-} /* end encodePartySubaddress_Full() */
-
-
-
-
[... 668 lines stripped ...]
More information about the thirdparty-commits
mailing list