/* * (CAPI*) * * An implementation of Common ISDN API 2.0 for * Asterisk / OpenPBX.org * * Copyright (C) 2005-2007 Cytronics & Melware * Copyright (C) 2007 Mario Goegel * * Armin Schindler * Mario Goegel * * This program is free software and may be modified and * distributed under the terms of the GNU Public License. */ #include #include #include #include #include #include #include "chan_capi20.h" #include "chan_capi.h" #include "chan_capi_qsig.h" #include "chan_capi_qsig_asn197ade.h" #include "chan_capi_qsig_asn197no.h" /* * Handle Operation: 1.3.12.9.0-3 ECMA/ISDN/NAMEPRESENTATION * * This function decodes the namepresentation facility * The name will be copied in the cid.cid_name field of the asterisk channel struct * * parameters * invoke struct, which contains encoded data from facility * i is pointer to capi channel * returns * nothing */ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i) { char callername[51]; /* ECMA defines max length to 50 */ unsigned int namelength = 0; unsigned int datalength; int myidx = 0; cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling Name Operation (id# %#x)\n", invoke->id); datalength = invoke->datalen; myidx = cc_qsig_asn197no_get_name(callername, ASN197NO_NAME_STRSIZE, &namelength, &myidx, invoke->data ); if (namelength > 0) { /* TODO: Maybe we do some charset conversions */ i->owner->cid.cid_name = strdup(callername); cc_verbose(1, 1, VERBOSE_PREFIX_4 " * received name (%i byte(s)): \"%s\"\n", namelength, callername); } /* if there was an sequence tag, we have more informations here, but we will ignore it at the moment */ } /* * Encode Operation: 1.3.12.9.0-3 ECMA/ISDN/NAMEPRESENTATION * * This function encodes the namepresentation facility * The name will be copied from the cid.cid_name field of the asterisk channel struct. * We create an invoke struct with the complete encoded invoke. * * parameters * buf is pointer to facility array, not used now * idx current idx in facility array, not used now * invoke struct, which contains encoded data for facility * i is pointer to capi channel * returns * always 0 */ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype) { const unsigned char oid[] = {0x2b,0x0c,0x09,0x00}; /* 1.3.12.9.0 */ int oid_len = sizeof(oid); unsigned char namebuf[51]; unsigned char data[255]; int dataidx = 0; int namelen = 0; if (i->owner->cid.cid_name) namelen = strlen(i->owner->cid.cid_name); if (namelen < 1) { /* There's no name available, try to take Interface-Name */ if (i->name) { if (strlen(i->name) >= 1) { if (namelen > 50) namelen = 50; namelen = strlen(i->name); memcpy(namebuf, i->name, namelen); } } } else { if (namelen > 50) namelen = 50; memcpy(namebuf, i->owner->cid.cid_name, namelen); } invoke->id = 1; invoke->descr_type = ASN1_OBJECTIDENTIFIER; invoke->oid_len = oid_len; memcpy(invoke->oid_bin, oid, oid_len); /* HACK: */ if (nametype) invoke->oid_bin[3] = 2; if (namelen>0) { data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */ data[dataidx++] = namelen; memcpy(&data[dataidx], namebuf, namelen); dataidx += namelen; } else { data[dataidx++] = 0x84; /* Name not available */ data[dataidx++] = 0; } invoke->datalen = dataidx; memcpy(invoke->data, data, dataidx); /* qsig_add_invoke(buf, idx, invoke); */ return 0; } /* * Handle Operation: 1.3.12.9.21 ECMA/ISDN/LEG_INFORMATION2 * * This function decodes the LEG INFORMATION2 facility * The datas will be copied in the some Asterisk channel variables -> see README.qsig * * parameters * invoke struct, which contains encoded data from facility * i is pointer to capi channel * returns * nothing */ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i) { unsigned int datalength; unsigned int seqlength = 0; int myidx = 0; unsigned int parameter = 0; unsigned int divCount = 0; unsigned int divReason = 0; unsigned int orgDivReason = 0; char tempstr[5]; char divertNum[ASN197ADE_NUMDIGITS_STRSIZE+1]; char origCalledNum[ASN197ADE_NUMDIGITS_STRSIZE+1]; char divertName[ASN197NO_NAME_STRSIZE+1]; char origCalledName[ASN197NO_NAME_STRSIZE+1]; unsigned int temp = 0; unsigned int temp2 = 0; divertNum[0] = 0; origCalledNum[0] = 0; divertNum[0] = 0; divertName[0] = 0; origCalledName[0] = 0; cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG LEG INFO2 (id# %#x)\n", invoke->id); if (invoke->data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */ /* We do not handle this, because it should start with an sequence tag */ cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - not a sequence\n"); return; } /* This facility is encoded as SEQUENCE */ seqlength = invoke->data[myidx++]; datalength = invoke->datalen; if (datalength < (seqlength+1)) { cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - buffer error\n"); return; } if (invoke->data[myidx++] == ASN1_INTEGER) divCount = cc_qsig_asn1_get_integer(invoke->data, &myidx); if (invoke->data[myidx++] == ASN1_ENUMERATED) divReason = cc_qsig_asn1_get_integer(invoke->data, &myidx); while (myidx < datalength) { parameter = (invoke->data[myidx++] & 0x0f); cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Found parameter %i\n", parameter); switch (parameter) { case 0: myidx++; /* Ignore Length of enumeration tag*/ if (invoke->data[myidx++] == ASN1_ENUMERATED) orgDivReason = cc_qsig_asn1_get_integer(invoke->data, &myidx); break; case 1: temp = cc_qsig_asn197ade_get_partynumber(divertNum, ASN197ADE_NUMDIGITS_STRSIZE, &myidx, invoke->data); if (temp) { myidx += temp; } break; case 2: temp = cc_qsig_asn197ade_get_partynumber(origCalledNum, ASN197ADE_NUMDIGITS_STRSIZE, &myidx, invoke->data); if (temp) { myidx += temp; } break; case 3: /* Redirecting Name */ myidx++; temp = cc_qsig_asn197no_get_name(divertName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data); if (temp) { myidx += temp; } break; case 4: /* origCalled Name */ myidx++; temp = cc_qsig_asn197no_get_name(origCalledName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data); if (temp) { myidx += temp; } break; } } snprintf(tempstr, 5, "%i", divReason); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_DIVREASON", tempstr); snprintf(tempstr, 5, "%i", orgDivReason); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_ODIVREASON", tempstr); snprintf(tempstr, 5, "%i", divCount); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_DIVCOUNT", tempstr); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_DIVNUM", divertNum); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_ODIVNUM", origCalledNum); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_DIVNAME", divertName); pbx_builtin_setvar_helper(i->owner, "QSIG_LI2_ODIVNAME", origCalledName); cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_LEG_INFO2: %i(%i), %ix %s->%s, %s->%s\n", divReason, orgDivReason, divCount, origCalledNum, divertNum, origCalledName, divertName); return; }