/* HNBAP common code */ /* (C) 2015 by Harald Welte * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * */ #include #include #include #include #include static const struct value_string hnbap_cause_radio_vals[] = { { CauseRadioNetwork_overload, "overload" }, { CauseRadioNetwork_unauthorised_Location, "unauthorized location" }, { CauseRadioNetwork_unauthorised_HNB, "unauthorized HNB" }, { CauseRadioNetwork_hNB_parameter_mismatch, "HNB parameter mismatch" }, { CauseRadioNetwork_invalid_UE_identity, "invalid UE identity" }, { CauseRadioNetwork_uE_not_allowed_on_this_HNB, "UE not allowed on this HNB" }, { CauseRadioNetwork_uE_unauthorised, "unauthorised UE" }, { CauseRadioNetwork_connection_with_UE_lost, "connection with UE lost" }, { CauseRadioNetwork_ue_RRC_release, "UE RRC release" }, { CauseRadioNetwork_hNB_not_registered, "HNB not registered" }, { CauseRadioNetwork_unspecified, "unspecified" }, { CauseRadioNetwork_normal, "normal" }, { CauseRadioNetwork_uE_relocated, "UE relocated" }, { CauseRadioNetwork_ue_registered_in_another_HNB, "UE registered in another HNB" }, { 0, NULL } }; static const struct value_string hnbap_cause_transp_vals[] = { { CauseTransport_transport_resource_unavailable, "transport resource unavailable" }, { CauseTransport_unspecified, "unspecified" }, { 0, NULL } }; static const struct value_string hnbap_cause_prot_vals[] = { { CauseProtocol_transfer_syntax_error, "syntax error" }, { CauseProtocol_abstract_syntax_error_reject, "abstract syntax error; reject" }, { CauseProtocol_abstract_syntax_error_ignore_and_notify, "abstract syntax error; ignore and notify" }, { CauseProtocol_message_not_compatible_with_receiver_state, "message not compatible with receiver state" }, { CauseProtocol_semantic_error, "semantic error" }, { CauseProtocol_unspecified, "unspecified" }, { CauseProtocol_abstract_syntax_error_falsely_constructed_message, "falsely constructed message" }, { 0, NULL } }; static const struct value_string hnbap_cause_misc_vals[] = { { CauseMisc_processing_overload, "processing overload" }, { CauseMisc_hardware_failure, "hardware failure" }, { CauseMisc_o_and_m_intervention, "OAM intervention" }, { CauseMisc_unspecified, "unspecified" }, { 0, NULL } }; char *hnbap_cause_str(Cause_t *cause) { static char buf[32]; switch (cause->present) { case Cause_PR_radioNetwork: snprintf(buf, sizeof(buf), "radio(%s)", get_value_string(hnbap_cause_radio_vals, cause->choice.radioNetwork)); break; case Cause_PR_transport: snprintf(buf, sizeof(buf), "transport(%s)", get_value_string(hnbap_cause_transp_vals, cause->choice.transport)); break; case Cause_PR_protocol: snprintf(buf, sizeof(buf), "protocol(%s)", get_value_string(hnbap_cause_prot_vals, cause->choice.protocol)); break; case Cause_PR_misc: snprintf(buf, sizeof(buf), "misc(%s)", get_value_string(hnbap_cause_misc_vals, cause->choice.misc)); break; } return buf; } static struct msgb *hnbap_msgb_alloc(void) { return msgb_alloc(1024, "HNBAP Tx"); } static struct msgb *_hnbap_gen_msg(HNBAP_PDU_t *pdu) { struct msgb *msg = hnbap_msgb_alloc(); asn_enc_rval_t rval; if (!msg) return NULL; rval = aper_encode_to_buffer(&asn_DEF_HNBAP_PDU, pdu, msg->data, msgb_tailroom(msg)); if (rval.encoded < 0) { LOGP(DHNBAP, LOGL_ERROR, "Error encoding type: %s\n", rval.failed_type->name); } msgb_put(msg, rval.encoded/8); return msg; } struct msgb *hnbap_generate_initiating_message( e_ProcedureCode procedureCode, Criticality_t criticality, asn_TYPE_descriptor_t * td, void *sptr) { struct msgb *msg; HNBAP_PDU_t pdu; int rc; memset(&pdu, 0, sizeof(HNBAP_PDU_t)); pdu.present = HNBAP_PDU_PR_initiatingMessage; pdu.choice.initiatingMessage.procedureCode = procedureCode; pdu.choice.initiatingMessage.criticality = criticality; rc = ANY_fromType_aper(&pdu.choice.initiatingMessage.value, td, sptr); if (rc < 0) { LOGP(DHNBAP, LOGL_ERROR, "Error in ANY_fromType_aper\n"); return NULL; } msg = _hnbap_gen_msg(&pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_PDU, &pdu); return msg; } struct msgb *hnbap_generate_successful_outcome( e_ProcedureCode procedureCode, Criticality_t criticality, asn_TYPE_descriptor_t * td, void *sptr) { struct msgb *msg; HNBAP_PDU_t pdu; int rc; memset(&pdu, 0, sizeof(HNBAP_PDU_t)); pdu.present = HNBAP_PDU_PR_successfulOutcome; pdu.choice.successfulOutcome.procedureCode = procedureCode; pdu.choice.successfulOutcome.criticality = criticality; rc = ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr); if (rc < 0) { LOGP(DHNBAP, LOGL_ERROR, "Error in ANY_fromType_aper\n"); return NULL; } msg = _hnbap_gen_msg(&pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_PDU, &pdu); return msg; } struct msgb *hnbap_generate_unsuccessful_outcome( e_ProcedureCode procedureCode, Criticality_t criticality, asn_TYPE_descriptor_t * td, void *sptr) { struct msgb *msg; HNBAP_PDU_t pdu; int rc; memset(&pdu, 0, sizeof(HNBAP_PDU_t)); pdu.present = HNBAP_PDU_PR_unsuccessfulOutcome; pdu.choice.unsuccessfulOutcome.procedureCode = procedureCode; pdu.choice.unsuccessfulOutcome.criticality = criticality; rc = ANY_fromType_aper(&pdu.choice.unsuccessfulOutcome.value, td, sptr); if (rc < 0) { LOGP(DHNBAP, LOGL_ERROR, "Error in ANY_fromType_aper\n"); return NULL; } msg = _hnbap_gen_msg(&pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_PDU, &pdu); return msg; } IE_t *hnbap_new_ie(ProtocolIE_ID_t id, Criticality_t criticality, asn_TYPE_descriptor_t * type, void *sptr) { IE_t *buff; int rc; if ((buff = CALLOC(1, sizeof(IE_t))) == NULL) { // Possible error on malloc return NULL; } buff->id = id; buff->criticality = criticality; rc = ANY_fromType_aper(&buff->value, type, sptr); if (rc < 0) { LOGP(DHNBAP, LOGL_ERROR, "Error in ANY_fromType_aper\n"); FREEMEM(buff); return NULL; } if (asn1_xer_print) if (xer_fprint(stdout, &asn_DEF_IE, buff) < 0) { FREEMEM(buff); return NULL; } return buff; }