/*! * \brief Decode the PresentedNumberUnscreened argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param party Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct rosePresentedNumberUnscreened *party) { int length; int seq_offset; const unsigned char *seq_end; if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s PresentedNumberUnscreened\n", name); } switch (tag) { case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0: if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); party->presentation = 0; /* presentationAllowedNumber */ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationAllowedNumber", tag, pos, seq_end, &party->number)); ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 1: party->presentation = 1; /* presentationRestricted */ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 2: party->presentation = 2; /* numberNotAvailableDueToInterworking */ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag, pos, end)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3: if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); party->presentation = 3; /* presentationRestrictedNumber */ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationRestrictedNumber", tag, pos, seq_end, &party->number)); ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); break; default: ASN1_DID_NOT_EXPECT_TAG(ctrl, tag); return NULL; } return pos; }
void pri_dump_event(struct pri *pri, pri_event *e) { if (!pri || !e) return; pri_message(pri, "Event type: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e); switch(e->gen.e) { case PRI_EVENT_DCHAN_UP: case PRI_EVENT_DCHAN_DOWN: break; case PRI_EVENT_CONFIG_ERR: pri_message(pri, "Error: %s", e->err.err); break; case PRI_EVENT_RESTART: pri_message(pri, "Restart on channel %d\n", e->restart.channel); case PRI_EVENT_RING: pri_message(pri, "Calling number: %s (%s, %s)\n", e->ring.callingnum, pri_plan2str(e->ring.callingplan), pri_pres2str(e->ring.callingpres)); pri_message(pri, "Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan)); pri_message(pri, "Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref); break; case PRI_EVENT_HANGUP: pri_message(pri, "Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause)); break; default: pri_message(pri, "Don't know how to dump events of type %d\n", e->gen.e); } }
/*! * \internal * \brief Decode the public or private network PartyNumber argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param party_number Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ static const unsigned char *rose_dec_NetworkPartyNumber(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct rosePartyNumber *party_number) { int32_t value; int length; int seq_offset; const unsigned char *seq_end; if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfNumber", tag, pos, seq_end, &value)); party_number->ton = value; ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_NUMERIC_STRING); ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "numberDigits", tag, pos, seq_end, party_number)); ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
/*! * \brief Decode the EctInform invoke argument parameters. * * \param ctrl D channel controller for diagnostic messages or global options. * \param tag Component tag that identified this structure. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param args Arguments to fill in from the decoded buffer. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args) { struct roseEtsiEctInform_ARG *ect_inform; int length; int seq_offset; const unsigned char *seq_end; int32_t value; if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " EctInform %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ect_inform = &args->etsi.EctInform; ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value)); ect_inform->status = value; if (pos < seq_end && *pos != ASN1_INDEF_TERM) { ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "redirectionNumber", tag, pos, seq_end, &ect_inform->redirection)); ect_inform->redirection_present = 1; } else { ect_inform->redirection_present = 0; } ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
/*! * \internal * \brief Decode the MessageID argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param msg_id Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ static const unsigned char *rose_dec_etsi_message_id(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct roseEtsiMessageID *msg_id) { int32_t value; int length; int seq_offset; const unsigned char *seq_end; ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE); if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s MessageID %s\n", name, asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER); ASN1_CALL(pos, asn1_dec_int(ctrl, "messageRef", tag, pos, seq_end, &value)); msg_id->reference_number = value; ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "status", tag, pos, seq_end, &value)); msg_id->status = value; ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
/*! * \brief Decode the NumberScreened argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param screened Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct roseNumberScreened *screened) { int32_t value; int length; int seq_offset; const unsigned char *seq_end; if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s NumberScreened %s\n", name, asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end, &screened->number)); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value)); screened->screening_indicator = value; ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
/*! * \brief Decode the PresentedAddressScreened argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param party Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct rosePresentedAddressScreened *party) { if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s PresentedAddressScreened\n", name); } switch (tag) { case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0: party->presentation = 0; /* presentationAllowedAddress */ ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationAllowedAddress", tag, pos, end, &party->screened)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 1: party->presentation = 1; /* presentationRestricted */ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 2: party->presentation = 2; /* numberNotAvailableDueToInterworking */ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag, pos, end)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3: party->presentation = 3; /* presentationRestrictedAddress */ ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationRestrictedAddress", tag, pos, end, &party->screened)); break; default: ASN1_DID_NOT_EXPECT_TAG(ctrl, tag); return NULL; } return pos; }
/*! * \brief Decode the Address argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param address Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct roseAddress *address) { int length; int seq_offset; const unsigned char *seq_end; if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s Address %s\n", name, asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end, &address->number)); if (pos < seq_end && *pos != ASN1_INDEF_TERM) { /* The optional subaddress must be present since there is something left. */ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos, seq_end, &address->subaddress)); } else { address->subaddress.length = 0; /* Subaddress not present */ } ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) { int i = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; int datalen = 0; int res = 0; do { GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n"); if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) { pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len); return -1; } if (comp->len == ASN1_LEN_INDEF) { datalen = strlen((char *)comp->data); res = datalen + 2; } else res = datalen = comp->len; memcpy(value->partyaddress, comp->data, datalen); value->partyaddress[datalen] = '\0'; return res + 2; } while(0); return -1; }
int redirectingreason_from_q931(struct pri *pri, int redirectingreason) { switch(pri->switchtype) { case PRI_SWITCH_QSIG: switch(redirectingreason) { case PRI_REDIR_UNKNOWN: return QSIG_DIVERT_REASON_UNKNOWN; case PRI_REDIR_FORWARD_ON_BUSY: return QSIG_DIVERT_REASON_CFB; case PRI_REDIR_FORWARD_ON_NO_REPLY: return QSIG_DIVERT_REASON_CFNR; case PRI_REDIR_UNCONDITIONAL: return QSIG_DIVERT_REASON_CFU; case PRI_REDIR_DEFLECTION: case PRI_REDIR_DTE_OUT_OF_ORDER: case PRI_REDIR_FORWARDED_BY_DTE: pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason); /* Fall through */ default: return QSIG_DIVERT_REASON_UNKNOWN; } default: switch(redirectingreason) { case PRI_REDIR_UNKNOWN: return Q952_DIVERT_REASON_UNKNOWN; case PRI_REDIR_FORWARD_ON_BUSY: return Q952_DIVERT_REASON_CFB; case PRI_REDIR_FORWARD_ON_NO_REPLY: return Q952_DIVERT_REASON_CFNR; case PRI_REDIR_DEFLECTION: return Q952_DIVERT_REASON_CD; case PRI_REDIR_UNCONDITIONAL: return Q952_DIVERT_REASON_CFU; case PRI_REDIR_DTE_OUT_OF_ORDER: case PRI_REDIR_FORWARDED_BY_DTE: pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason); /* Fall through */ default: return Q952_DIVERT_REASON_UNKNOWN; } } }
/*! * \brief Decode the MWIDeactivate invoke argument parameters. * * \param ctrl D channel controller for diagnostic messages or global options. * \param tag Component tag that identified this structure. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param args Arguments to fill in from the decoded buffer. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args) { int32_t value; int length; int seq_offset; const unsigned char *seq_end; struct roseEtsiMWIDeactivate_ARG *mwi_deactivate; mwi_deactivate = &args->etsi.MWIDeactivate; ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE); if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " MWIDeactivate %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end, &mwi_deactivate->receiving_user_number)); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value)); mwi_deactivate->basic_service = value; /* * A sequence specifies an ordered list of component types. * However, for simplicity we are not checking the order of * the remaining optional components. */ mwi_deactivate->controlling_user_number.length = 0; mwi_deactivate->mode_present = 0; while (pos < seq_end && *pos != ASN1_INDEF_TERM) { ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); switch (tag) { default: ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos, seq_end, &mwi_deactivate->controlling_user_number)); break; case ASN1_TYPE_ENUMERATED: ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, seq_end, &value)); mwi_deactivate->mode = value; mwi_deactivate->mode_present = 1; break; } } ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
/*! * \brief Decode the PartyNumber argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param party_number Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct rosePartyNumber *party_number) { if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s PartyNumber\n", name); } party_number->ton = 0; /* unknown */ switch (tag & ~ASN1_PC_MASK) { case ASN1_CLASS_CONTEXT_SPECIFIC | 0: party_number->plan = 0; /* Unknown PartyNumber */ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "unknownPartyNumber", tag, pos, end, party_number)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 1: /* Must be constructed but we will not check for it for simplicity. */ party_number->plan = 1; /* Public PartyNumber */ ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "publicPartyNumber", tag, pos, end, party_number)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 2: party_number->plan = 2; /* NSAP encoded PartyNumber */ ASN1_CALL(pos, rose_dec_NSAPPartyNumber(ctrl, "nsapEncodedPartyNumber", tag, pos, end, party_number)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 3: party_number->plan = 3; /* Data PartyNumber (Not used) */ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "dataPartyNumber", tag, pos, end, party_number)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 4: party_number->plan = 4; /* Telex PartyNumber (Not used) */ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "telexPartyNumber", tag, pos, end, party_number)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 5: /* Must be constructed but we will not check for it for simplicity. */ party_number->plan = 5; /* Private PartyNumber */ ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "privatePartyNumber", tag, pos, end, party_number)); break; case ASN1_CLASS_CONTEXT_SPECIFIC | 8: party_number->plan = 8; /* National Standard PartyNumber (Not used) */ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "nationalStandardPartyNumber", tag, pos, end, party_number)); break; default: ASN1_DID_NOT_EXPECT_TAG(ctrl, tag); return NULL; } return pos; }
static int redirectingreason_for_q931(struct pri *pri, int redirectingreason) { switch(pri->switchtype) { case PRI_SWITCH_QSIG: switch(redirectingreason) { case QSIG_DIVERT_REASON_UNKNOWN: return PRI_REDIR_UNKNOWN; case QSIG_DIVERT_REASON_CFU: return PRI_REDIR_UNCONDITIONAL; case QSIG_DIVERT_REASON_CFB: return PRI_REDIR_FORWARD_ON_BUSY; case QSIG_DIVERT_REASON_CFNR: return PRI_REDIR_FORWARD_ON_NO_REPLY; default: pri_message(pri, "!! Unknown Q.SIG diversion reason %d\n", redirectingreason); return PRI_REDIR_UNKNOWN; } default: switch(redirectingreason) { case Q952_DIVERT_REASON_UNKNOWN: return PRI_REDIR_UNKNOWN; case Q952_DIVERT_REASON_CFU: return PRI_REDIR_UNCONDITIONAL; case Q952_DIVERT_REASON_CFB: return PRI_REDIR_FORWARD_ON_BUSY; case Q952_DIVERT_REASON_CFNR: return PRI_REDIR_FORWARD_ON_NO_REPLY; case Q952_DIVERT_REASON_CD: return PRI_REDIR_DEFLECTION; case Q952_DIVERT_REASON_IMMEDIATE: pri_message(pri, "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n"); return PRI_REDIR_UNKNOWN; /* ??? */ default: pri_message(pri, "!! Unknown Q.952 diversion reason %d\n", redirectingreason); return PRI_REDIR_UNKNOWN; } } }
static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) { int i = 0; int size = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; /* Fill in default values */ value->ton = PRI_TON_UNKNOWN; value->npi = PRI_NPI_E163_E164; value->pres = -1; /* Data is not available */ do { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */ value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; size = rose_address_decode(pri, call, comp->data, comp->len, value); ASN1_FIXUP_LEN(comp, size); return size + 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */ if (comp->len != 0) { /* must be NULL */ pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n"); return -1; } value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED; return 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */ if (comp->len != 0) { /* must be NULL */ pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n"); return -1; } value->pres = PRES_NUMBER_NOT_AVAILABLE; return 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */ value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED; size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2; ASN1_FIXUP_LEN(comp, size); return size + 2; default: pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type); } return -1; } while (0); return -1; }
/*! * \internal * \brief Decode the User PartySubaddress argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param party_subaddress Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ static const unsigned char *rose_dec_UserSubaddress(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct rosePartySubaddress *party_subaddress) { size_t str_len; int32_t odd_count; int length; int seq_offset; const unsigned char *seq_end; party_subaddress->type = 0; /* UserSpecified */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s UserSpecified %s\n", name, asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); /* SubaddressInformation */ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING); ASN1_CALL(pos, asn1_dec_string_bin(ctrl, "subaddressInformation", tag, pos, seq_end, sizeof(party_subaddress->u.user_specified.information), party_subaddress->u.user_specified.information, &str_len)); party_subaddress->length = str_len; if (pos < seq_end && *pos != ASN1_INDEF_TERM) { /* * The optional odd count indicator must be present since there * is something left. */ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN); ASN1_CALL(pos, asn1_dec_boolean(ctrl, "oddCount", tag, pos, seq_end, &odd_count)); party_subaddress->u.user_specified.odd_count = odd_count; party_subaddress->u.user_specified.odd_count_present = 1; } else { party_subaddress->u.user_specified.odd_count = 0; party_subaddress->u.user_specified.odd_count_present = 0; } ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
static int typeofnumber_for_q931(struct pri *pri, int ton) { switch (ton) { case Q932_TON_UNKNOWN: return PRI_TON_UNKNOWN; case Q932_TON_INTERNATIONAL: return PRI_TON_INTERNATIONAL; case Q932_TON_NATIONAL: return PRI_TON_NATIONAL; case Q932_TON_NET_SPECIFIC: return PRI_TON_NET_SPECIFIC; case Q932_TON_SUBSCRIBER: return PRI_TON_SUBSCRIBER; case Q932_TON_ABBREVIATED: return PRI_TON_ABBREVIATED; default: pri_message(pri, "!! Invalid Q.932 TypeOfNumber %d\n", ton); return PRI_TON_UNKNOWN; } }
int typeofnumber_from_q931(struct pri *pri, int ton) { switch(ton) { case PRI_TON_INTERNATIONAL: return Q932_TON_INTERNATIONAL; case PRI_TON_NATIONAL: return Q932_TON_NATIONAL; case PRI_TON_NET_SPECIFIC: return Q932_TON_NET_SPECIFIC; case PRI_TON_SUBSCRIBER: return Q932_TON_SUBSCRIBER; case PRI_TON_ABBREVIATED: return Q932_TON_ABBREVIATED; case PRI_TON_RESERVED: default: pri_message(pri, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton); /* fall through */ case PRI_TON_UNKNOWN: return Q932_TON_UNKNOWN; } }
static void dump_apdu(struct pri *pri, unsigned char *c, int len) { #define MAX_APDU_LENGTH 255 int i; char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */ if (len > MAX_APDU_LENGTH) return; snprintf(message, sizeof(message)-1, " ["); for (i=0; i<len; i++) snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " %02x", c[i]); snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " ] - ["); for (i=0; i<len; i++) { if (c[i] < 20 || c[i] >= 128) snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "°"); else snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "%c", c[i]); } snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "]\n"); pri_message(pri, message); }
/*! * \brief Decode the AddressScreened argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param screened Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct roseAddressScreened *screened) { int32_t value; int length; int seq_offset; const unsigned char *seq_end; if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s AddressScreened %s\n", name, asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end, &screened->number)); ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value)); screened->screening_indicator = value; if (pos < seq_end && *pos != ASN1_INDEF_TERM) { /* The optional subaddress must be present since there is something left. */ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos, seq_end, &screened->subaddress)); } else { screened->subaddress.length = 0; /* Subaddress not present */ } ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan) { struct pri_sr req; if (!pri || !c) return -1; pri_sr_init(&req); pri_sr_set_connection_call_independent(&req); req.caller = caller; req.callerplan = callerplan; req.callername = callername; req.callerpres = callerpres; req.called = called; req.calledplan = calledplan; if(mwi_message_send(pri, c, &req, 0) < 0) { pri_message(pri, "Unable to send MWI deactivate message\n"); return -1; } return q931_setup(pri, c, &req); }
/* Don't call any other pri functions on this */ int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan) { struct pri_sr req; if (!pri || !c) return -1; pri_sr_init(&req); pri_sr_set_connection_call_independent(&req); req.caller = caller; req.callerplan = callerplan; req.callername = callername; req.callerpres = callerpres; req.called = called; req.calledplan = calledplan; if (mwi_message_send(pri, c, &req, 1) < 0) { pri_message(pri, "Unable to send MWI activate message\n"); return -1; } /* Do more stuff when we figure out that the CISC stuff works */ return q931_setup(pri, c, &req); }
/*! * \brief Decode the PartySubaddress argument parameters. * * \param ctrl D channel controller for any diagnostic messages. * \param name Field name * \param tag Component tag that identified this production. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param party_subaddress Parameter storage to fill. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end, struct rosePartySubaddress *party_subaddress) { if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " %s PartySubaddress\n", name); } switch (tag) { case ASN1_TAG_SEQUENCE: ASN1_CALL(pos, rose_dec_UserSubaddress(ctrl, "user", tag, pos, end, party_subaddress)); break; case ASN1_TYPE_OCTET_STRING: case ASN1_TYPE_OCTET_STRING | ASN1_PC_CONSTRUCTED: ASN1_CALL(pos, rose_dec_NSAPSubaddress(ctrl, "nsap", tag, pos, end, party_subaddress)); break; default: ASN1_DID_NOT_EXPECT_TAG(ctrl, tag); return NULL; } return pos; }
/*! * \brief Decode the MWIIndicate invoke argument parameters. * * \param ctrl D channel controller for diagnostic messages or global options. * \param tag Component tag that identified this structure. * \param pos Starting position of the ASN.1 component length. * \param end End of ASN.1 decoding data buffer. * \param args Arguments to fill in from the decoded buffer. * * \retval Start of the next ASN.1 component on success. * \retval NULL on error. */ const unsigned char *rose_dec_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args) { int32_t value; size_t str_len; int length; int seq_offset; int explicit_offset; const unsigned char *explicit_end; const unsigned char *seq_end; const unsigned char *save_pos; struct roseEtsiMWIIndicate_ARG *mwi_indicate; mwi_indicate = &args->etsi.MWIIndicate; ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE); if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " MWIIndicate %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, end, &length)); ASN1_END_SETUP(seq_end, seq_offset, length, pos, end); /* * A sequence specifies an ordered list of component types. * However, for simplicity we are not checking the order of * the remaining optional components. */ mwi_indicate->controlling_user_number.length = 0; mwi_indicate->basic_service_present = 0; mwi_indicate->number_of_messages_present = 0; mwi_indicate->controlling_user_provided_number.length = 0; mwi_indicate->time_present = 0; mwi_indicate->message_id_present = 0; while (pos < seq_end && *pos != ASN1_INDEF_TERM) { save_pos = pos; ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag)); switch (tag) { case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1: /* Remove EXPLICIT tag */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length)); ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end); ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag)); ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos, explicit_end, &mwi_indicate->controlling_user_number)); ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2: /* Remove EXPLICIT tag */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length)); ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end); ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED); ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, explicit_end, &value)); mwi_indicate->basic_service = value; mwi_indicate->basic_service_present = 1; ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3: /* Remove EXPLICIT tag */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length)); ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end); ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag)); ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER); ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end, &value)); mwi_indicate->number_of_messages = value; mwi_indicate->number_of_messages_present = 1; ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4: /* Remove EXPLICIT tag */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length)); ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end); ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag)); ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag, pos, explicit_end, &mwi_indicate->controlling_user_provided_number)); ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5: /* Remove EXPLICIT tag */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length)); ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end); ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag)); ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME); ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end, sizeof(mwi_indicate->time.str), mwi_indicate->time.str, &str_len)); mwi_indicate->time_present = 1; ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end); break; case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6: /* Remove EXPLICIT tag */ if (ctrl->debug & PRI_DEBUG_APDU) { pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag)); } ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length)); ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end); ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag)); ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos, explicit_end, &mwi_indicate->message_id)); mwi_indicate->message_id_present = 1; ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end); break; default: pos = save_pos; goto cancel_options; } } cancel_options:; ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end); return pos; }
static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call) { int i = 0, j, compsp = 0; struct rose_component *comp, *compstk[10]; unsigned char buffer[256]; int len = 253; if (!strlen(call->callername)) { return -1; } buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); i++; /* Interpretation component */ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Invoke component contents */ /* Invoke ID */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); /* Operation Tag */ /* ROSE operationId component */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2); /* ROSE ARGUMENT component */ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* ROSE DivertingLegInformation2.diversionCounter component */ /* Always is 1 because other isn't available in the current design */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1); /* ROSE DivertingLegInformation2.diversionReason component */ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason)); /* ROSE DivertingLegInformation2.divertingNr component */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Redirecting information always not screened */ switch(call->redirectingpres) { case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: if (call->redirectingnum && strlen(call->redirectingnum)) { ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* NPI of redirected number is not supported in the current design */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4)); j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum)); if (j < 0) return -1; i += j; ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); break; } /* fall through */ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: case PRES_PROHIB_USER_NUMBER_NOT_SCREENED: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); break; /* Don't know how to handle this */ case PRES_ALLOWED_NETWORK_NUMBER: case PRES_PROHIB_NETWORK_NUMBER: case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); break; default: pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres); case PRES_NUMBER_NOT_AVAILABLE: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i); break; }
static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len) { int i = 0; int diversion_counter; int diversion_reason; char origcalledname[50] = "", redirectingname[50] = ""; struct addressingdataelements_presentednumberunscreened divertingnr; struct addressingdataelements_presentednumberunscreened originalcallednr; struct rose_component *comp = NULL; unsigned char *vdata = sequence->data; int res = 0; /* Data checks */ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */ pri_message(pri, "Invalid DivertingLegInformation2Type argument\n"); return -1; } if (sequence->len == ASN1_LEN_INDEF) { len -= 4; /* For the 2 extra characters at the end * and two characters of header */ } else len -= 2; do { /* diversionCounter stuff */ GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do it diversionCounter is of type 0x%x\n"); ASN1_GET_INTEGER(comp, diversion_counter); NEXT_COMPONENT(comp, i); /* diversionReason stuff */ GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation2 component received\n"); ASN1_GET_INTEGER(comp, diversion_reason); NEXT_COMPONENT(comp, i); diversion_reason = redirectingreason_for_q931(pri, diversion_reason); if(pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter); pri_message(NULL, "Length of message is %d\n", len); for(; i < len; NEXT_COMPONENT(comp, i)) { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]); if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason); break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr); /* TODO: Fix indefinite length form hacks */ ASN1_FIXUP_LEN(comp, res); comp->len = res; if (res < 0) return -1; if (pri->debug & PRI_DEBUG_APDU) { pri_message(pri, " Received divertingNr '%s'\n", divertingnr.partyaddress); pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi); } break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr); if (res < 0) return -1; ASN1_FIXUP_LEN(comp, res); comp->len = res; if (pri->debug & PRI_DEBUG_APDU) { pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress); pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi); } break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname)); if (res < 0) return -1; ASN1_FIXUP_LEN(comp, res); comp->len = res; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received RedirectingName '%s'\n", redirectingname); break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname)); if (res < 0) return -1; ASN1_FIXUP_LEN(comp, res); comp->len = res; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname); break; default: if (comp->type == 0 && comp->len == 0) { break; /* Found termination characters */ } pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type); return -1; } } if (divertingnr.pres >= 0) { call->redirectingplan = divertingnr.npi; call->redirectingpres = divertingnr.pres; call->redirectingreason = diversion_reason; libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum)); } if (originalcallednr.pres >= 0) { call->origcalledplan = originalcallednr.npi; call->origcalledpres = originalcallednr.pres; libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum)); } libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname)); libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname)); return 0; } while (0); return -1; }
static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) { int i = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; int res = 0; do { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_UNKNOWN; value->ton = PRI_TON_UNKNOWN; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */ res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp); if (res < 0) return -1; value->npi = PRI_NPI_UNKNOWN; value->ton = PRI_TON_UNKNOWN; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */ res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_E163_E164; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */ pri_message(pri, "!! NsapEncodedNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */ if(rose_number_digits_decode(pri, call, comp->data, comp->len, value)) return -1; value->npi = PRI_NPI_X121 /* ??? */; value->ton = PRI_TON_UNKNOWN /* ??? */; pri_message(pri, "!! dataPartyNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_F69 /* ??? */; value->ton = PRI_TON_UNKNOWN /* ??? */; pri_message(pri, "!! telexPartyNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */ pri_message(pri, "!! privatePartyNumber isn't handled\n"); value->npi = PRI_NPI_PRIVATE; return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_NATIONAL; value->ton = PRI_TON_NATIONAL; break; default: pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type); return -1; } ASN1_FIXUP_LEN(comp, res); NEXT_COMPONENT(comp, i); if(i < len) pri_message(pri, "!! not all information is handled from Address component\n"); return res + 2; } while (0); return -1; }