From f8db61b554a59b12d330618fc41979a920523814 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 18 Dec 2015 17:29:59 +0100 Subject: [PATCH] First compiling (and leak-free) RANAP message generation functions encoding correctness still needs to be verified at this point. At least they generate some binary output without failing somewhere earlier in the encoding process - and they don't leave any leaked memory behind, see talloc_report() at the end of test-ranap.c:main(). --- src/Makefile.am | 2 +- src/asn1helpers.h | 1 + src/ranap_msg_factory.c | 625 ++++++++++++++++++++++++++++++++++++++++ src/ranap_msg_factory.h | 22 ++ src/tests/Makefile.am | 17 +- src/tests/test-ranap.c | 564 +++++++----------------------------- 6 files changed, 769 insertions(+), 462 deletions(-) create mode 100644 src/ranap_msg_factory.c create mode 100644 src/ranap_msg_factory.h diff --git a/src/Makefile.am b/src/Makefile.am index e0b916d4..156baa4d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ COMMON_LDADD = -lsctp bin_PROGRAMS = hnbgw -hnbgw_SOURCES = hnbap_encoder.c hnbap_decoder.c rua_encoder.c rua_decoder.c ranap_common.c rua_common.c hnbap_common.c iu_helpers.c asn1helpers.c hnbgw.c hnbgw_hnbap.c hnbgw_rua.c hnbgw_ranap.c ranap_decoder.c ranap_encoder.c +hnbgw_SOURCES = hnbap_encoder.c hnbap_decoder.c rua_encoder.c rua_decoder.c ranap_common.c rua_common.c hnbap_common.c iu_helpers.c asn1helpers.c hnbgw.c hnbgw_hnbap.c hnbgw_rua.c hnbgw_ranap.c ranap_decoder.c ranap_encoder.c ranap_msg_factory.c hnbgw_LDADD = $(OSMOCORE_LIBS) $(OSMOVTY_LIBS) $(OSMOGSM_LIBS) $(ASN1C_LIBS) $(COMMON_LDADD) hnbap/libosmo-asn1-hnbap.a rua/libosmo-asn1-rua.a ranap/libosmo-asn1-ranap.a diff --git a/src/asn1helpers.h b/src/asn1helpers.h index bb0f4de0..d68743d2 100644 --- a/src/asn1helpers.h +++ b/src/asn1helpers.h @@ -2,6 +2,7 @@ #include +#include "asn_system.h" #include "BIT_STRING.h" #include "OCTET_STRING.h" diff --git a/src/ranap_msg_factory.c b/src/ranap_msg_factory.c new file mode 100644 index 00000000..e98936a8 --- /dev/null +++ b/src/ranap_msg_factory.c @@ -0,0 +1,625 @@ +/* high-level RANAP messsage generation 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 "asn1helpers.h" +#include "iu_helpers.h" + +#include "ranap_common.h" +#include "ranap_ies_defs.h" +#include "ranap_msg_factory.h" + +#include "hnbgw.h" + +/*! \brief allocate a new long and assing a value to it */ +static long *new_long(long in) +{ + long *out = CALLOC(1, sizeof(long)); + *out = in; + return out; +} + +/*! \brief generate RANAP DIRECT TRANSFER message */ +struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas_len) +{ + RANAP_DirectTransferIEs_t ies; + RANAP_DirectTransfer_t dt; + struct msgb *msg; + int rc; + + memset(&ies, 0, sizeof(ies)); + memset(&dt, 0, sizeof(dt)); + + /* only SAPI optional field shall be present for CN->RNC */ + ies.presenceMask = DIRECTTRANSFERIES_RANAP_SAPI_PRESENT; + + if (sapi == 3) + ies.sapi = RANAP_SAPI_sapi_3; + else + ies.sapi = RANAP_SAPI_sapi_0; + + ies.nas_pdu.buf = (uint8_t *) nas; + ies.nas_pdu.size = nas_len; + + /* ies -> dt */ + rc = ranap_encode_directtransferies(&dt, &ies); + + /* dt -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_DirectTransfer, + RANAP_Criticality_reject, + &asn_DEF_RANAP_DirectTransfer, + &dt); + + /* release dynamic allocations attached to dt */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_DirectTransfer, &dt); + + return msg; +} + +static const enum RANAP_IntegrityProtectionAlgorithm ip_alg[2] = { + RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA1, + RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA2, +}; + +static const RANAP_EncryptionAlgorithm_t enc_alg[2] = { + RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorith_UEA1, + RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorithm_UEA2, +}; + +/*! \brief generate RANAP SECURITY MODE COMMAND message */ +struct msgb *ranap_new_msg_sec_mod_cmd(const uint8_t *ik, const uint8_t *ck) +{ + RANAP_SecurityModeCommandIEs_t ies; + RANAP_SecurityModeCommand_t out; + struct msgb *msg; + int i, rc; + + memset(&ies, 0, sizeof(ies)); + memset(&out, 0, sizeof(out)); + + ies.presenceMask = SECURITYMODECOMMANDIES_RANAP_ENCRYPTIONINFORMATION_PRESENT; + + for (i = 0; i < ARRAY_SIZE(ip_alg); i++) { + /* needs to be dynamically allocated, as + * SET_OF_free() will call FREEMEM() on it */ + RANAP_IntegrityProtectionAlgorithm_t *alg = CALLOC(1, sizeof(*alg)); + *alg = ip_alg[i]; + ASN_SEQUENCE_ADD(&ies.integrityProtectionInformation.permittedAlgorithms, alg); + } + + BIT_STRING_fromBuf(&ies.integrityProtectionInformation.key, ik, 16*8); + + if (ck) { + for (i = 0; i < ARRAY_SIZE(ip_alg); i++) { + /* needs to be dynamically allocated, as + * SET_OF_free() will call FREEMEM() on it */ + RANAP_EncryptionAlgorithm_t *alg = CALLOC(1, sizeof(*alg)); + *alg = enc_alg[i]; + ASN_SEQUENCE_ADD(&ies.encryptionInformation.permittedAlgorithms, alg); + } + BIT_STRING_fromBuf(&ies.encryptionInformation.key, ck, 16*8); + } + + ies.keyStatus = RANAP_KeyStatus_new; /* FIXME */ + + /* ies -> out */ + rc = ranap_encode_securitymodecommandies(&out, &ies); + + /* release dynamic allocations attached to ies */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_IntegrityProtectionInformation, &ies.integrityProtectionInformation); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_EncryptionInformation, &ies.encryptionInformation); + + /* out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_SecurityModeControl, + RANAP_Criticality_reject, + &asn_DEF_RANAP_SecurityModeCommand, + &out); + + /* release dynamic allocations attached to out */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_SecurityModeCommand, &out); + + return msg; +} + +/*! \brief generate RANAP COMMON ID message */ +struct msgb *ranap_new_msg_common_id(const char *imsi) +{ + RANAP_CommonID_IEs_t ies; + RANAP_CommonID_t out; + struct msgb *msg; + int rc; + + memset(&ies, 0, sizeof(ies)); + memset(&out, 0, sizeof(out)); + + if (imsi) { + uint8_t *imsi_buf = CALLOC(1, 16); + rc = encode_iu_imsi(imsi_buf, 16, imsi); + ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI; + ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf; + ies.permanentNAS_UE_ID.choice.iMSI.size = rc; + } else + ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_NOTHING; + + /* ies -> out */ + rc = ranap_encode_commonid_ies(&out, &ies); + /* release dynamic allocations attached to ies */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_PermanentNAS_UE_ID, &ies.permanentNAS_UE_ID); + if (rc < 0) + return NULL; + + /* out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_CommonID, + RANAP_Criticality_ignore, + &asn_DEF_RANAP_CommonID, + &out); + + /* release dynamic allocations attached to out */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_CommonID, &out); + + return msg; +} + +/*! \brief generate RANAP IU RELEASE COMMAND message */ +struct msgb *ranap_new_msg_iu_rel_cmd(const RANAP_Cause_t *cause_in) +{ + RANAP_Iu_ReleaseCommandIEs_t ies; + RANAP_Iu_ReleaseCommand_t out; + struct msgb *msg; + int rc; + + memset(&ies, 0, sizeof(ies)); + memset(&out, 0, sizeof(out)); + + memcpy(&ies.cause, cause_in, sizeof(ies.cause)); + + /* ies -> out */ + rc = ranap_encode_iu_releasecommandies(&out, &ies); + if (rc < 0) + return NULL; + + /* out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Iu_Release, + RANAP_Criticality_reject, + &asn_DEF_RANAP_Iu_ReleaseCommand, + &out); + + /* release dynamic allocations attached to out */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Iu_ReleaseCommand, &out); + + return msg; +} + +/*! \brief generate RANAP PAGING COMMAND message */ +struct msgb *ranap_new_msg_paging_cmd(const char *imsi, const uint32_t *tmsi, int is_ps, uint32_t cause) +{ + RANAP_PagingIEs_t ies; + RANAP_Paging_t out; + struct msgb *msg; + uint8_t *imsi_buf = CALLOC(1, 16); + int rc; + + memset(&ies, 0, sizeof(ies)); + memset(&out, 0, sizeof(out)); + + /* put together the 'ies' */ + if (is_ps) + ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_ps_domain; + else + ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_cs_domain; + + rc = encode_iu_imsi(imsi_buf, 16, imsi); + ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI; + ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf; + ies.permanentNAS_UE_ID.choice.iMSI.size = rc; + + if (tmsi) { + uint32_t *tmsi_buf = CALLOC(1, sizeof(*tmsi_buf)); + *tmsi_buf = *tmsi; + ies.presenceMask |= PAGINGIES_RANAP_TEMPORARYUE_ID_PRESENT; + if (is_ps) { + ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_p_TMSI; + ies.temporaryUE_ID.choice.tMSI.buf = tmsi_buf; + ies.temporaryUE_ID.choice.tMSI.size = sizeof(*tmsi_buf); + } else { + ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_tMSI; + ies.temporaryUE_ID.choice.p_TMSI.buf = tmsi_buf; + ies.temporaryUE_ID.choice.p_TMSI.size = sizeof(*tmsi_buf); + } + } + + if (cause) { + ies.presenceMask |= PAGINGIES_RANAP_PAGINGCAUSE_PRESENT; + ies.pagingCause = cause; + } + + /* ies -> out */ + rc = ranap_encode_pagingies(&out, &ies); + /* release dynamic allocation attached to ies */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_PermanentNAS_UE_ID, &ies.permanentNAS_UE_ID); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_TemporaryUE_ID, &ies.temporaryUE_ID); + if (rc < 0) + return NULL; + + /* out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Paging, + RANAP_Criticality_reject, + &asn_DEF_RANAP_Paging, + &out); + + /* release dynamic allocations attached to out */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Paging, &out); + + return msg; +} + +static RANAP_SDU_ErrorRatio_t *new_sdu_error_ratio(long mantissa, long exponent) +{ + RANAP_SDU_ErrorRatio_t *err = CALLOC(1, sizeof(*err)); + + err->mantissa = mantissa; + err->exponent = exponent; + + return err; +} + + +static RANAP_SDU_FormatInformationParameterItem_t * +new_format_info_pars(long sdu_size) +{ + RANAP_SDU_FormatInformationParameterItem_t *fmti = CALLOC(1, sizeof(*fmti)); + fmti->subflowSDU_Size = new_long(sdu_size); + return fmti; +} + +enum sdu_par_profile { + SDUPAR_P_VOICE0, + SDUPAR_P_VOICE1, + SDUPAR_P_VOICE2, + SDUPAR_P_DATA, +}; + +/* See Chapter 5 of TS 26.102 */ +static RANAP_SDU_ParameterItem_t *new_sdu_par_item(enum sdu_par_profile profile) +{ + RANAP_SDU_ParameterItem_t *sdui = CALLOC(1, sizeof(*sdui)); + RANAP_SDU_FormatInformationParameters_t *fmtip = CALLOC(1, sizeof(*fmtip)); + RANAP_SDU_FormatInformationParameterItem_t *fmti; + + switch (profile) { + case SDUPAR_P_VOICE0: + sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 5); + sdui->residualBitErrorRatio.mantissa = 1; + sdui->residualBitErrorRatio.exponent = 6; + sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_yes; + sdui->sDU_FormatInformationParameters = fmtip; + fmti = new_format_info_pars(81); + ASN_SEQUENCE_ADD(fmtip, fmti); + fmti = new_format_info_pars(39); + ASN_SEQUENCE_ADD(fmtip, fmti); + /* FIXME: could be 10 SDU descriptors for AMR! */ + break; + case SDUPAR_P_VOICE1: + sdui->residualBitErrorRatio.mantissa = 1; + sdui->residualBitErrorRatio.exponent = 3; + sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration; + sdui->sDU_FormatInformationParameters = fmtip; + fmti = new_format_info_pars(103); + ASN_SEQUENCE_ADD(fmtip, fmti); + fmti = new_format_info_pars(0); + ASN_SEQUENCE_ADD(fmtip, fmti); + /* FIXME: could be 10 SDU descriptors for AMR! */ + break; + case SDUPAR_P_VOICE2: + sdui->residualBitErrorRatio.mantissa = 5; + sdui->residualBitErrorRatio.exponent = 3; + sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration; + sdui->sDU_FormatInformationParameters = fmtip; + fmti = new_format_info_pars(60); + ASN_SEQUENCE_ADD(fmtip, fmti); + fmti = new_format_info_pars(0); + ASN_SEQUENCE_ADD(fmtip, fmti); + /* FIXME: could be 10 SDU descriptors for AMR! */ + break; + case SDUPAR_P_DATA: + sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 4); + sdui->residualBitErrorRatio.mantissa = 1; + sdui->residualBitErrorRatio.exponent = 5; + sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no; + FREEMEM(fmtip); + break; + } + + return sdui; +} + +static RANAP_AllocationOrRetentionPriority_t * +new_alloc_ret_prio(RANAP_PriorityLevel_t level, int capability, int vulnerability, + int queueing_allowed) +{ + RANAP_AllocationOrRetentionPriority_t *arp = CALLOC(1, sizeof(*arp)); + + arp->priorityLevel = level; + + if (capability) + arp->pre_emptionCapability = RANAP_Pre_emptionCapability_may_trigger_pre_emption; + else + arp->pre_emptionCapability = RANAP_Pre_emptionCapability_shall_not_trigger_pre_emption; + + if (vulnerability) + arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_pre_emptable; + else + arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_not_pre_emptable; + + if (queueing_allowed) + arp->queuingAllowed = RANAP_QueuingAllowed_queueing_allowed; + else + arp->queuingAllowed = RANAP_QueuingAllowed_queueing_not_allowed; + + return arp; +} + +/* See Chapter 5 of TS 26.102 */ +static RANAP_RAB_Parameters_t *new_rab_par_voice(void) +{ + RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab)); + RANAP_SDU_ParameterItem_t *sdui; + + rab->trafficClass = RANAP_TrafficClass_conversational; + rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_symmetric_bidirectional; + + ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(12200)); + rab->guaranteedBitRate = CALLOC(1, sizeof(*rab->guaranteedBitRate)); + ASN_SEQUENCE_ADD(rab->guaranteedBitRate, new_long(12200)); + rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested; + rab->maxSDU_Size = 244; + + sdui = new_sdu_par_item(SDUPAR_P_VOICE0); + ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); + sdui = new_sdu_par_item(SDUPAR_P_VOICE1); + ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); + sdui = new_sdu_par_item(SDUPAR_P_VOICE2); + ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); + + rab->transferDelay = new_long(80); + rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 1, 0); + + rab->sourceStatisticsDescriptor = new_long(RANAP_SourceStatisticsDescriptor_speech); + + return rab; +} + +static RANAP_RAB_Parameters_t *new_rab_par_data(void) +{ + RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab)); + RANAP_SDU_ParameterItem_t *sdui; + + rab->trafficClass = RANAP_TrafficClass_background; + rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_asymmetric_bidirectional; + + ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(16000000)); + ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(8000000)); + rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested; + rab->maxSDU_Size = 8000; + + sdui = new_sdu_par_item(SDUPAR_P_DATA); + ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); + + rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 0, 0); + + /* FIXME: RAB-Parameter-ExtendedMaxBitrateList for 42Mbps? */ + + return rab; +} + +static RANAP_TransportLayerInformation_t *new_transp_info_rtp(uint32_t ip, uint16_t port) +{ + RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli)); + uint32_t *ipbuf = CALLOC(1, sizeof(*ipbuf)); + uint8_t binding_id[4]; + + binding_id[0] = port >> 8; + binding_id[1] = port & 0xff; + binding_id[2] = binding_id[3] = 0; + + asn1_u32_to_bitstring(&tli->transportLayerAddress, ipbuf, htonl(ip)); + tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_bindingID; + OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID, + (const char *) binding_id, sizeof(binding_id)); + + return tli; +} + +static RANAP_TransportLayerInformation_t *new_transp_info_gtp(uint32_t ip, uint32_t tei) +{ + RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli)); + uint32_t *ipbuf = CALLOC(1, sizeof(*ipbuf)); + uint32_t binding_buf = htonl(tei); + + asn1_u32_to_bitstring(&tli->transportLayerAddress, ipbuf, htonl(ip)); + tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_gTP_TEI; + OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID, + (const char *) &binding_buf, sizeof(binding_buf)); + + return tli; +} + +static RANAP_UserPlaneInformation_t *new_upi(long mode, uint8_t mode_versions) +{ + RANAP_UserPlaneInformation_t *upi = CALLOC(1, sizeof(*upi)); + uint16_t *buf = CALLOC(1, sizeof(*buf)); + + *buf = mode_versions; + + upi->userPlaneMode = mode; + upi->uP_ModeVersions.buf = buf; + upi->uP_ModeVersions.size = sizeof(*buf); + upi->uP_ModeVersions.bits_unused = 0; + + return upi; +} + + +static void assign_new_ra_id(RANAP_RAB_ID_t *id, uint8_t rab_id) +{ + uint8_t *buf = CALLOC(1, sizeof(*buf)); + *buf = rab_id << 3; + + id->buf = buf; + id->size = 1; + id->bits_unused = 0; +} + +/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for CS (voice) */ +struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, uint16_t rtp_port) +{ + RANAP_ProtocolIE_FieldPair_t *pair; + RANAP_RAB_AssignmentRequestIEs_t ies; + RANAP_RAB_AssignmentRequest_t out; + struct msgb *msg; + int rc; + + memset(&ies, 0, sizeof(ies)); + memset(&out, 0, sizeof(out)); + + /* only assingnment is present, no release */ + ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT; + + /* put together the 'First' part */ + RANAP_RAB_SetupOrModifyItemFirst_t first; + memset(&first, 0, sizeof(first)); + assign_new_ra_id(&first.rAB_ID, rab_id); + //first.nAS_SynchronisationIndicator = FIXME; + first.rAB_Parameters = new_rab_par_voice(); + first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_support_mode_for_predefined_SDU_sizes, 1); /* 2? */ + first.transportLayerInformation = new_transp_info_rtp(rtp_ip, rtp_port); + + /* put together the 'Second' part */ + RANAP_RAB_SetupOrModifyItemSecond_t second; + memset(&second, 0, sizeof(second)); + + /* Build an IE Pair out of first and second part: + * (first, second) -> pair */ + pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first, + RANAP_Criticality_ignore, + &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second); + + /* the pair has been made, we can release any of its elements */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second); + + /* Add the pair to the list of IEs of the RAB ass.req */ + ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, pair); + + /* encode the IEs into the actual assignment request: + * ies -> out */ + rc = ranap_encode_rab_assignmentrequesties(&out, &ies); + /* 'out' has been generated, we can now release the input */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList, + &ies.raB_SetupOrModifyList); + if (rc < 0) + return NULL; + + /* generate an Initiating Mesasage: out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_AssignmentRequest, &out); + + /* 'msg' has been generated, we cann now release the input 'out' */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, &out); + + return msg; +} + +/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for PS (data) */ +struct msgb *ranap_new_msg_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip, uint32_t gtp_tei) +{ + RANAP_ProtocolIE_FieldPair_t *pair; + RANAP_RAB_AssignmentRequestIEs_t ies; + RANAP_RAB_AssignmentRequest_t out; + RANAP_DataVolumeReportingIndication_t *dat_vol_ind; + struct msgb *msg; + int rc; + + memset(&ies, 0, sizeof(ies)); + memset(&out, 0, sizeof(out)); + + /* only assingnment is present, no release */ + ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT; + + /* put together the 'First' part */ + RANAP_RAB_SetupOrModifyItemFirst_t first; + memset(&first, 0, sizeof(first)); + assign_new_ra_id(&first.rAB_ID, rab_id); + //first.nAS_SynchronisationIndicator = FIXME; + first.rAB_Parameters = new_rab_par_data(); + first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_transparent_mode, 1); + first.transportLayerInformation = new_transp_info_rtp(gtp_ip, gtp_tei); + + /* put together the 'Second' part */ + RANAP_RAB_SetupOrModifyItemSecond_t second; + memset(&second, 0, sizeof(second)); + second.pDP_TypeInformation = CALLOC(1, sizeof(*second.pDP_TypeInformation)); + ASN_SEQUENCE_ADD(second.pDP_TypeInformation, new_long(RANAP_PDP_Type_ipv4)); + dat_vol_ind = CALLOC(1, sizeof(*dat_vol_ind)); + *dat_vol_ind = RANAP_DataVolumeReportingIndication_do_not_report; + second.dataVolumeReportingIndication = dat_vol_ind; + second.dl_GTP_PDU_SequenceNumber = new_long(0); + second.ul_GTP_PDU_SequenceNumber = new_long(0); + + /* Build an IE Pair out of first and second part: + * (first, second) -> pair */ + pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, + &first, RANAP_Criticality_ignore, + &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, + &second); + + /* the pair has been made, we can release any of its elements */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second); + + /* Add the pair to the list of IEs of the RAB ass.req */ + ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, pair); + + /* encode the IEs into the actual assignment request: + * ies -> out */ + rc = ranap_encode_rab_assignmentrequesties(&out, &ies); + /* 'out' has been generated, we can now release the input */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList, + &ies.raB_SetupOrModifyList); + if (rc < 0) + return NULL; + + /* generate an Initiating Mesasage: out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_AssignmentRequest, &out); + + /* 'msg' has been generated, we cann now release the input 'out' */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, &out); + + return msg; +} diff --git a/src/ranap_msg_factory.h b/src/ranap_msg_factory.h new file mode 100644 index 00000000..b721045e --- /dev/null +++ b/src/ranap_msg_factory.h @@ -0,0 +1,22 @@ +#pragma once + +/*! \brief generate RANAP DIRECT TRANSFER message */ +struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas_len); + +/*! \brief generate RANAP SECURITY MODE COMMAND message */ +struct msgb *ranap_new_msg_sec_mod_cmd(const uint8_t *ik, const uint8_t *ck); + +/*! \brief generate RANAP COMMON ID message */ +struct msgb *ranap_new_msg_common_id(const char *imsi); + +/*! \brief generate RANAP IU RELEASE COMMAND message */ +struct msgb *ranap_new_msg_iu_rel_cmd(const RANAP_Cause_t *cause_in); + +/*! \brief generate RANAP PAGING COMMAND message */ +struct msgb *ranap_new_msg_paging_cmd(const char *imsi, const uint32_t *tmsi, int is_ps, uint32_t cause); + +/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for CS (voice) */ +struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, uint16_t rtp_port); + +/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for PS (data) */ +struct msgb *ranap_new_msg_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip, uint32_t gtp_tei); diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index f7a9670e..a44ad2cf 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -2,22 +2,27 @@ AM_CFLAGS = $(OSMOVTY_CFLAGS) $(OSMOCORE_CFLAGS) $(OSMOGSM_CFLAGS) $(ASN1C_CFLAG COMMON_LIBS = $(OSMOVTY_LIBS) $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(ASN1C_LIBS) -lsctp -check_PROGRAMS = test-helpers test-hnbap hnb-test +check_PROGRAMS = test-ranap test-helpers test-hnbap hnb-test HNBAP_FILES = $(top_builddir)/src/hnbap_common.c $(top_builddir)/src/hnbap_decoder.c $(top_builddir)/src/hnbap_encoder.c RUA_FILES = $(top_builddir)/src/rua_common.c $(top_builddir)/src/rua_decoder.c $(top_builddir)/src/rua_encoder.c -RANAP_FILES = $(top_builddir)/src/ranap_common.c ### $(top_builddir)/src/ranap_decoder.c $(top_builddir)/src/ranap_encoder.c +RANAP_FILES = $(top_builddir)/src/ranap_common.c \ + $(top_builddir)/src/ranap_decoder.c \ + $(top_builddir)/src/ranap_encoder.c \ + $(top_builddir)/src/ranap_msg_factory.c +HELPER_FILES = $(top_builddir)/src/iu_helpers.c $(top_builddir)/src/asn1helpers.c -test_helpers_SOURCES = $(top_builddir)/src/iu_helpers.c $(top_builddir)/src/asn1helpers.c test-helpers.c +test_helpers_SOURCES = $(HELPER_FILES) test-helpers.c test_helpers_LDADD = $(COMMON_LIBS) -test_hnbap_SOURCES = $(top_builddir)/src/iu_helpers.c $(top_builddir)/src/asn1helpers.c $(top_builddir)/src/hnbap_common.c $(top_builddir)/src/hnbap_decoder.c test-hnbap.c +test_hnbap_SOURCES = $(HELPER_FILES) $(top_builddir)/src/hnbap_common.c $(top_builddir)/src/hnbap_decoder.c test-hnbap.c test_hnbap_LDADD = $(COMMON_LIBS) $(top_builddir)/src/hnbap/libosmo-asn1-hnbap.a -hnb_test_SOURCES = $(top_builddir)/src/iu_helpers.c $(top_builddir)/src/asn1helpers.c $(HNBAP_FILES) $(RUA_FILES) $(RANAP_FILES) hnb-test.c +hnb_test_SOURCES = $(HELPER_FILES) $(HNBAP_FILES) $(RUA_FILES) $(RANAP_FILES) hnb-test.c hnb_test_LDADD = $(COMMON_LIBS) $(top_builddir)/src/hnbap/libosmo-asn1-hnbap.a $(top_builddir)/src/rua/libosmo-asn1-rua.a $(top_builddir)/src/ranap/libosmo-asn1-ranap.a - +test_ranap_SOURCES = $(HELPER_FILES) $(RANAP_FILES) test-ranap.c +test_ranap_LDADD = $(COMMON_LIBS) $(top_builddir)/src/ranap/libosmo-asn1-ranap.a # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac diff --git a/src/tests/test-ranap.c b/src/tests/test-ranap.c index f3d24cdc..76624731 100644 --- a/src/tests/test-ranap.c +++ b/src/tests/test-ranap.c @@ -1,478 +1,132 @@ +/* (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 "asn1helpers.h" #include "iu_helpers.h" #include "ranap_common.h" #include "ranap_ies_defs.h" +#include "ranap_msg_factory.h" -/* This is just some non-compiling work in progress code to generate the - * minimum set of RANAP messages that the core network side needs to send - * towards the RNC */ +#include "hnbgw.h" -static long *new_long(long in) -{ - long *out = CALLOC(1, sizeof(long)); - *out = in; - return out; -} +void *talloc_asn1_ctx; +int asn1_xer_print = 1; -int ranap_tx_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas_len) -{ - RANAP_DirectTransferIEs_t ies; - RANAP_DirectTransfer_t dt; - struct msgb *msg; - int rc; +extern void *tall_msgb_ctx; - memset(&ies, 0, sizeof(ies)); - - /* only SAPI optional field shall be present for CN->RNC */ - ies.presenceMask = DIRECTTRANSFERIES_RANAP_SAPI_PRESENT; - - if (sapi == 3) - ies.sapi = RANAP_SAPI_sapi_3; - else - ies.sapi = RANAP_SAPI_sapi_0; - - ies.nas_pdu.buf = (uint8_t *) nas; - ies.nas_pdu.size = nas_len; - - rc = ranap_encode_directtransferies(&dt, &ies); - - msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_DirectTransfer, - RANAP_Criticality_reject, - &asn_DEF_RANAP_DirectTransfer, - &dt); - /* FIXME: Hand that to RUA or SCCP */ -} - -static const enum RANAP_IntegrityProtectionAlgorithm ip_alg[2] = { - RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA1, - RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA2, +static const struct log_info_cat log_cat[] = { + [DMAIN] = { + .name = "DMAIN", .loglevel = LOGL_INFO, .enabled = 1, + .color = "", + .description = "Main program", + }, + [DHNBAP] = { + .name = "DHNBAP", .loglevel = LOGL_DEBUG, .enabled = 1, + .color = "", + .description = "Home Node B Application Part", + }, }; -static const RANAP_EncryptionAlgorithm_t enc_alg[2] = { - RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorith_UEA1, - RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorithm_UEA2, +static const struct log_info hnbgw_log_info = { + .cat = log_cat, + .num_cat = ARRAY_SIZE(log_cat), }; -int ranap_tx_sec_mod_cmd(void) + +int main(int argc, char **argv) { - RANAP_SecurityModeCommandIEs_t ies; - RANAP_SecurityModeCommand_t out; + uint8_t nas_buf[] = { 0xaa, 0xbb, 0xcc }; struct msgb *msg; + const char *imsi = "901700123456789"; + uint32_t tmsi = 0x01234567; + uint32_t rtp_ip = 0x0a0b0c0d; + uint16_t rtp_port = 2342; + uint32_t gtp_ip = 0x1a1b1c1d; + uint32_t gtp_tei = 0x11223344; + uint8_t ik[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + uint8_t ck[16] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; int i, rc; - memset(&ies, 0, sizeof(ies)); + //asn_debug = 1; - ies.presenceMask = SECURITYMODECOMMANDIES_RANAP_ENCRYPTIONINFORMATION_PRESENT; + talloc_asn1_ctx = talloc_named_const(NULL, 1, "ASN"); + msgb_set_talloc_ctx(talloc_named_const(NULL, 1, "msgb")); - for (i = 0; i < ARRAY_SIZE(ip_alg); i++) { - /* needs to be dynamically allocated, as - * SET_OF_free() will call FREEMEM() on it */ - RANAP_IntegrityProtectionAlgorithm_t *alg = CALLOC(1, sizeof(*alg)); - *alg = ip_alg[i]; - ASN_SEQUENCE_ADD(&ies.integrityProtectionInformation.permittedAlgorithms, alg); + rc = osmo_init_logging(&hnbgw_log_info); + if (rc < 0) + exit(1); + + for (i = 0; i < 1; i++) { + printf("\n==> DIRECT TRANSFER\n"); + msg = ranap_new_msg_dt(0, nas_buf, sizeof(nas_buf)); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); + + printf("\n==> SECURITY MODE COMMAND\n"); + msg = ranap_new_msg_sec_mod_cmd(ik, ck); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); + + printf("\n==> COMMON ID\n"); + msg = ranap_new_msg_common_id(imsi); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); + + printf("\n==> IU RELEASE CMD\n"); + RANAP_Cause_t cause = { .present = RANAP_Cause_PR_radioNetwork, + .choice.radioNetwork = RANAP_CauseRadioNetwork_radio_connection_with_UE_Lost }; + msg = ranap_new_msg_iu_rel_cmd(&cause); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); + + printf("\n==> PAGING CMD\n"); + msg = ranap_new_msg_paging_cmd(imsi, &tmsi, 0, RANAP_PagingCause_terminating_conversational_call); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); + + printf("\n==> RAB ASSIGNMENT COMMAND (VOICE)\n"); + msg = ranap_new_msg_rab_assign_voice(1, rtp_ip, rtp_port); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); + + printf("\n==> RAB ASSIGNMENT COMMAND (DATA)\n"); + msg = ranap_new_msg_rab_assign_data(2, gtp_ip, gtp_tei); + if (msg) + printf("%s\n", msgb_hexdump(msg)); + msgb_free(msg); } - ies.integrityProtectionInformation.key; /* FIXME */ - if (0) { - for (i = 0; i < ARRAY_SIZE(ip_alg); i++) { - /* needs to be dynamically allocated, as - * SET_OF_free() will call FREEMEM() on it */ - RANAP_EncryptionAlgorithm_t *alg = CALLOC(1, sizeof(*alg)); - *alg = enc_alg[i]; - ASN_SEQUENCE_ADD(&ies.encryptionInformation.permittedAlgorithms, alg); - } - ies.encryptionInformation.key; /* FIXME */ - } - - ies.keyStatus = RANAP_KeyStatus_new; /* FIXME */ - - rc = ranap_encode_securitymodecommandies(&out, &ies); - - asn_sequence_empty(&ies.integrityProtectionInformation.permittedAlgorithms); - asn_sequence_empty(&ies.encryptionInformation.permittedAlgorithms); - - msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_SecurityModeControl, - RANAP_Criticality_reject, - &asn_DEF_RANAP_SecurityModeCommand, - &out); -} - -int ranap_tx_common_id(const char *imsi) -{ - RANAP_CommonID_IEs_t ies; - RANAP_CommonID_t out; - struct msgb *msg; - int rc; - - memset(&ies, 0, sizeof(ies)); - - if (imsi) { - ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI; - ies.permanentNAS_UE_ID.choice.iMSI; /* FIXME */ - } else - ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_NOTHING; - - rc = ranap_encode_commonid_ies(&out, &ies); - - msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_CommonID, - RANAP_Criticality_ignore, - &asn_DEF_RANAP_CommonID, - &out); -} - -int ranap_tx_iu_rel_cmd(RANAP_Cause_t cause) -{ - RANAP_Iu_ReleaseCommandIEs_t ies; - RANAP_Iu_ReleaseCommand_t out; - struct msgb *msg; - int rc; - - memset(&ies, 0, sizeof(ies)); - - ies.cause = cause; - - rc = ranap_encode_iu_releasecommandies(&out, &ies); - - msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Iu_Release, - RANAP_Criticality_reject, - &asn_DEF_RANAP_Iu_ReleaseCommand, - &out); -} - -int ranap_tx_paging_cmd(const char *imsi, uint32_t *tmsi, int is_ps, uint32_t cause) -{ - RANAP_PagingIEs_t ies; - RANAP_Paging_t out; - struct msgb *msg; - uint8_t *imsi_buf = CALLOC(1, 16); - int rc; - - memset(&ies, 0, sizeof(ies)); - - if (is_ps) - ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_ps_domain; - else - ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_cs_domain; - - rc = encode_iu_imsi(imsi_buf, 16, imsi); - ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI; - ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf; - ies.permanentNAS_UE_ID.choice.iMSI.size = rc; - - if (tmsi) { - ies.presenceMask |= PAGINGIES_RANAP_TEMPORARYUE_ID_PRESENT; - if (is_ps) { - ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_p_TMSI; - ies.temporaryUE_ID.choice.tMSI; - } else { - ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_tMSI; - ies.temporaryUE_ID.choice.p_TMSI; - } - } - - if (cause) { - ies.presenceMask |= PAGINGIES_RANAP_PAGINGCAUSE_PRESENT; - ies.pagingCause = cause; - } - - rc = ranap_encode_pagingies(&out, &ies); - - msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Paging, - RANAP_Criticality_reject, - &asn_DEF_RANAP_Paging, - &out); -} - -static RANAP_SDU_ErrorRatio_t *new_sdu_error_ratio(long mantissa, long exponent) -{ - RANAP_SDU_ErrorRatio_t *err = CALLOC(1, sizeof(*err)); - - err->mantissa = mantissa; - err->exponent = exponent; - - return err; -} - - -static RANAP_SDU_FormatInformationParameterItem_t * -new_format_info_pars(long sdu_size) -{ - RANAP_SDU_FormatInformationParameterItem_t *fmti = CALLOC(1, sizeof(*fmti)); - fmti->subflowSDU_Size = new_long(sdu_size); - return fmti; -} - -enum sdu_par_profile { - SDUPAR_P_VOICE0, - SDUPAR_P_VOICE1, - SDUPAR_P_VOICE2, - SDUPAR_P_DATA, -}; - -/* See Chapter 5 of TS 26.102 */ -static RANAP_SDU_ParameterItem_t *new_sdu_par_item(enum sdu_par_profile profile) -{ - RANAP_SDU_ParameterItem_t *sdui = CALLOC(1, sizeof(*sdui)); - RANAP_SDU_FormatInformationParameters_t *fmtip = CALLOC(1, sizeof(*fmtip)); - RANAP_SDU_FormatInformationParameterItem_t *fmti; - - switch (profile) { - case SDUPAR_P_VOICE0: - sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 5); - sdui->residualBitErrorRatio.mantissa = 1; - sdui->residualBitErrorRatio.exponent = 6; - sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_yes; - sdui->sDU_FormatInformationParameters = fmtip; - fmti = new_format_info_pars(81); - ASN_SEQUENCE_ADD(fmtip, fmti); - fmti = new_format_info_pars(39); - ASN_SEQUENCE_ADD(fmtip, fmti); - /* FIXME: could be 10 SDU descriptors for AMR! */ - break; - case SDUPAR_P_VOICE1: - sdui->residualBitErrorRatio.mantissa = 1; - sdui->residualBitErrorRatio.exponent = 3; - sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration; - fmti = new_format_info_pars(103); - ASN_SEQUENCE_ADD(fmtip, fmti); - fmti = new_format_info_pars(0); - ASN_SEQUENCE_ADD(fmtip, fmti); - /* FIXME: could be 10 SDU descriptors for AMR! */ - break; - case SDUPAR_P_VOICE2: - sdui->residualBitErrorRatio.mantissa = 5; - sdui->residualBitErrorRatio.exponent = 3; - sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration; - fmti = new_format_info_pars(60); - ASN_SEQUENCE_ADD(fmtip, fmti); - fmti = new_format_info_pars(0); - ASN_SEQUENCE_ADD(fmtip, fmti); - /* FIXME: could be 10 SDU descriptors for AMR! */ - break; - case SDUPAR_P_DATA: - sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 4); - sdui->residualBitErrorRatio.mantissa = 1; - sdui->residualBitErrorRatio.exponent = 5; - sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no; - break; - } - - return sdui; -} - -static RANAP_AllocationOrRetentionPriority_t * -new_alloc_ret_prio(RANAP_PriorityLevel_t level, int capability, int vulnerability, - int queueing_allowed) -{ - RANAP_AllocationOrRetentionPriority_t *arp = CALLOC(1, sizeof(*arp)); - - arp->priorityLevel = level; - - if (capability) - arp->pre_emptionCapability = RANAP_Pre_emptionCapability_may_trigger_pre_emption; - else - arp->pre_emptionCapability = RANAP_Pre_emptionCapability_shall_not_trigger_pre_emption; - - if (vulnerability) - arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_pre_emptable; - else - arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_not_pre_emptable; - - if (queueing_allowed) - arp->queuingAllowed = RANAP_QueuingAllowed_queueing_allowed; - else - arp->queuingAllowed = RANAP_QueuingAllowed_queueing_not_allowed; - - return arp; -} - -/* See Chapter 5 of TS 26.102 */ -static RANAP_RAB_Parameters_t *new_rab_par_voice(void) -{ - RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab)); - RANAP_SDU_ParameterItem_t *sdui; - - rab->trafficClass = RANAP_TrafficClass_conversational; - rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_symmetric_bidirectional; - - ASN_SEQUENCE_ADD(&rab->maxBitrate, new_long(12200)); - rab->guaranteedBitRate = CALLOC(1, sizeof(*rab->guaranteedBitRate)); - ASN_SEQUENCE_ADD(&rab->guaranteedBitRate, new_long(12200)); - rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested; - rab->maxSDU_Size = 244; - - RANAP_SDU_Parameters_t *sdup = CALLOC(1, sizeof(*sdup)); - ASN_SEQUENCE_ADD(&sdup->list, sdui); - - sdui = new_sdu_par_item(SDUPAR_P_VOICE0); - ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); - sdui = new_sdu_par_item(SDUPAR_P_VOICE1); - ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); - sdui = new_sdu_par_item(SDUPAR_P_VOICE2); - ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); - - rab->transferDelay = new_long(80); - rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 1, 0); - - rab->sourceStatisticsDescriptor = new_long(RANAP_SourceStatisticsDescriptor_speech); - - return rab; -} - -static RANAP_RAB_Parameters_t *new_rab_par_data(void) -{ - RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab)); - RANAP_SDU_ParameterItem_t *sdui; - - rab->trafficClass = RANAP_TrafficClass_background; - rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_asymmetric_bidirectional; - - ASN_SEQUENCE_ADD(&rab->maxBitrate, new_long(16000000)); - ASN_SEQUENCE_ADD(&rab->maxBitrate, new_long(8000000)); - rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested; - rab->maxSDU_Size = 8000; - - sdui = new_sdu_par_item(SDUPAR_P_DATA); - ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui); - - rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 0, 0); - - /* FIXME: RAB-Parameter-ExtendedMaxBitrateList for 42Mbps? */ - - return rab; -} - -static RANAP_TransportLayerInformation_t *new_transp_info_rtp(uint32_t ip, uint16_t port) -{ - RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli)); - uint32_t *ipbuf = CALLOC(1, sizeof(*ipbuf)); - uint8_t binding_id[4]; - - binding_id[0] = port >> 8; - binding_id[1] = port & 0xff; - binding_id[2] = binding_id[3] = 0; - - asn1_u32_to_bitstring(&tli->transportLayerAddress, ipbuf, htonl(ip)); - tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_bindingID; - OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID, - (const char *) binding_id, sizeof(binding_id)); - - return tli; -} - -static RANAP_TransportLayerInformation_t *new_transp_info_gtp(uint32_t ip, uint32_t tei) -{ - RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli)); - uint32_t *ipbuf = CALLOC(1, sizeof(*ipbuf)); - uint32_t binding_buf = htonl(tei); - - asn1_u32_to_bitstring(&tli->transportLayerAddress, ipbuf, htonl(ip)); - tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_gTP_TEI; - OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID, - (const char *) &binding_buf, sizeof(binding_buf)); - - return tli; -} - -static RANAP_UserPlaneInformation_t *new_upi(long mode, uint8_t mode_versions) -{ - RANAP_UserPlaneInformation_t *upi = CALLOC(1, sizeof(*upi)); - uint8_t *buf = CALLOC(1, sizeof(*buf)); - - *buf = mode_versions; - - upi->userPlaneMode = mode; - upi->uP_ModeVersions.buf = buf; - upi->uP_ModeVersions.size = 1; - upi->uP_ModeVersions.bits_unused = 0; - - return upi; -} - - -static void assign_new_ra_id(RANAP_RAB_ID_t *id, uint8_t rab_id) -{ - uint8_t *buf = CALLOC(1, sizeof(*buf)); - *buf = rab_id << 3; - - id->buf = buf; - id->size = 1; - id->bits_unused = 0; -} - -int ranap_tx_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, uint16_t rtp_port) -{ - RANAP_ProtocolIE_FieldPair_t *pair; - RANAP_RAB_AssignmentRequestIEs_t ies; - RANAP_RAB_AssignmentRequest_t out; - int rc; - - memset(&ies, 0, sizeof(ies)); - - /* only assingnment is present, no release */ - ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT; - - RANAP_RAB_SetupOrModifyItemFirst_t first; - - assign_new_ra_id(&first.rAB_ID, rab_id); - //first.nAS_SynchronisationIndicator = FIXME; - first.rAB_Parameters = new_rab_par_voice(); - first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_support_mode_for_predefined_SDU_sizes, 1); /* 2? */ - first.transportLayerInformation = new_transp_info_rtp(rtp_ip, rtp_port); - - RANAP_RAB_SetupOrModifyItemSecond_t second; - memset(&second, 0, sizeof(second)); - - pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem, - RANAP_Criticality_reject, - &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first, - RANAP_Criticality_ignore, - &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second); - - ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, pair); - - rc = ranap_encode_rab_assignmentrequesties(&out, &ies); -} - -int ranap_tx_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip, uint16_t gtp_port) -{ - RANAP_ProtocolIE_FieldPair_t *pair; - RANAP_RAB_AssignmentRequestIEs_t ies; - RANAP_RAB_AssignmentRequest_t out; - RANAP_DataVolumeReportingIndication_t *dat_vol_ind = CALLOC(1, sizeof(*dat_vol_ind)); - int rc; - - memset(&ies, 0, sizeof(ies)); - - /* only assingnment is present, no release */ - ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT; - - RANAP_RAB_SetupOrModifyItemFirst_t first; - - assign_new_ra_id(&first.rAB_ID, rab_id); - //first.nAS_SynchronisationIndicator = FIXME; - first.rAB_Parameters = new_rab_par_data(); - first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_transparent_mode, 1); - first.transportLayerInformation = new_transp_info_rtp(gtp_ip, gtp_port); - - RANAP_RAB_SetupOrModifyItemSecond_t second; - memset(&second, 0, sizeof(second)); - second.pDP_TypeInformation = CALLOC(1, sizeof(*second.pDP_TypeInformation)); - ASN_SEQUENCE_ADD(&second.pDP_TypeInformation, new_long(RANAP_PDP_Type_ipv4)); - *dat_vol_ind = RANAP_DataVolumeReportingIndication_do_not_report; - second.dataVolumeReportingIndication = dat_vol_ind; - second.dl_GTP_PDU_SequenceNumber = new_long(0); - second.ul_GTP_PDU_SequenceNumber = new_long(0); - - pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem, - RANAP_Criticality_reject, - &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first, - RANAP_Criticality_ignore, - &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second); - - ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, pair); - - rc = ranap_encode_rab_assignmentrequesties(&out, &ies); + printf("report\n"); + talloc_report(talloc_asn1_ctx, stdout); + talloc_report(tall_msgb_ctx, stdout); + //talloc_report(NULL, stdout); + printf("exit\n"); + exit(0); }