dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/test_common.c A tests/test_common.h M tests/testsuite.at 8 files changed, 699 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/1
diff --git a/configure.ac b/configure.ac index 3e02bd9..4dc8087 100644 --- a/configure.ac +++ b/configure.ac @@ -233,6 +233,7 @@ src/osmo-hnbgw/Makefile tests/Makefile tests/atlocal + tests/ranap_rab_ass/Makefile doc/Makefile doc/examples/Makefile doc/manuals/Makefile diff --git a/include/osmocom/hnbgw/ranap_rab_ass.h b/include/osmocom/hnbgw/ranap_rab_ass.h new file mode 100644 index 0000000..94caa43 --- /dev/null +++ b/include/osmocom/hnbgw/ranap_rab_ass.h @@ -0,0 +1,18 @@ +#pragma once + +int ranap_rab_ass_req_decode(RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies, const uint8_t *data, + unsigned int len); +int ranap_rab_ass_req_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies); + +int ranap_rab_ass_resp_decode(RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies, const uint8_t *data, + unsigned int len); +int ranap_rab_ass_resp_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies); + +int ranap_rab_ass_req_extract_inet_addr(char *addr, uint16_t *port, uint8_t *rab_id, const uint8_t *data, + unsigned int data_len); +int ranap_rab_ass_resp_extract_inet_addr(char *addr, uint16_t *port, const uint8_t *data, unsigned int data_len); + +int ranap_rab_ass_req_replace_inet_addr(uint8_t *data, unsigned int data_len, const char *addr, uint32_t port); +int ranap_rab_ass_resp_replace_inet_addr(uint8_t *data, unsigned int data_len, const char *addr, uint32_t port); diff --git a/src/osmo-hnbgw/Makefile.am b/src/osmo-hnbgw/Makefile.am index bda8633..0948170 100644 --- a/src/osmo-hnbgw/Makefile.am +++ b/src/osmo-hnbgw/Makefile.am @@ -37,6 +37,7 @@ hnbgw_vty.c \ context_map.c \ hnbgw_cn.c \ + ranap_rab_ass.c \ $(NULL)
osmo_hnbgw_LDADD = \ diff --git a/src/osmo-hnbgw/ranap_rab_ass.c b/src/osmo-hnbgw/ranap_rab_ass.c new file mode 100644 index 0000000..c8fd3fe --- /dev/null +++ b/src/osmo-hnbgw/ranap_rab_ass.c @@ -0,0 +1,557 @@ +/* (C) 2021 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * All Rights Reserved + * + * Author: Philipp Maier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +/* Note: This files contains tools to decode and re-encode the RAB-AssignmentRequest. This set of tools is used by + * mgcp_fsm.c to extract and manipulate the transportLayerAddress. */ + +#include <errno.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/ranap/ranap_common.h> +#include <osmocom/ranap/iu_helpers.h> +#include <asn1c/asn1helpers.h> + +/* Decode a RAB-AssignmentRequest message down to request IEs. */ +int ranap_rab_ass_req_decode(RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies, const uint8_t *data, + unsigned int len) +{ + int rc; + asn_dec_rval_t dec_ret; + RANAP_RANAP_PDU_t _ranap_pdu; + RANAP_RANAP_PDU_t *ranap_pdu = &_ranap_pdu; + + /* NOTE: The caller must take care of freeing the raB_SetupOrModifyList that is contained in the result using: + * ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList, decoded.raB_SetupOrModifyList); */ + + memset(ranap_pdu, 0, sizeof(*ranap_pdu)); + memset(rab_assignment_request_ies, 0, sizeof(*rab_assignment_request_ies)); + + /* Decode the RANAP PDU (outer shell) */ + dec_ret = aper_decode(NULL, &asn_DEF_RANAP_RANAP_PDU, (void **)&ranap_pdu, data, len, 0, 0); + if (dec_ret.code != RC_OK) { + RANAP_DEBUG("Error in RANAP ASN.1 decode\n"); + return -EINVAL; + } + + /* We expect this to be an initiating message */ + if (ranap_pdu->present != RANAP_RANAP_PDU_PR_initiatingMessage) { + RANAP_DEBUG("RAB Assignment request does not contain an initiating message\n"); + rc = -EINVAL; + goto error; + } + + /* We expect the procedure code to match, this should always be the case since the procedure code is already + * matched by the code pathes before and we won't even attempt to enter this code path with a procedure code + * other then RANAP_ProcedureCode_id_RAB_Assignment */ + if (ranap_pdu->choice.initiatingMessage.procedureCode != RANAP_ProcedureCode_id_RAB_Assignment) { + RANAP_DEBUG("Procedure code indicates that this message is not a RAB Assignment!\n"); + rc = -EINVAL; + goto error; + } + + /* Decode RAB assignment request IEs (inner shell) */ + rc = ranap_decode_rab_assignmentrequesties(rab_assignment_request_ies, + &ranap_pdu->choice.initiatingMessage.value); + if (rc != 0) { + RANAP_DEBUG("Unable to decode RAB Assignment Request IEs!\n"); + rc = -EINVAL; + goto error; + } + + rc = 0; +error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RANAP_PDU, ranap_pdu); + return rc; +} + +/* Encode a RAB-AssignmentRequest message from given request IEs. */ +int ranap_rab_ass_req_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies) +{ + int rc; + struct msgb *msg; + + RANAP_RAB_AssignmentRequest_t _rab_assignment_request; + RANAP_RAB_AssignmentRequest_t *rab_assignment_request = &_rab_assignment_request; + memset(rab_assignment_request, 0, sizeof(*rab_assignment_request)); + + rc = ranap_encode_rab_assignmentrequesties(rab_assignment_request, rab_assignment_request_ies); + if (rc < 0) + return -EINVAL; + + /* generate an Initiating Mesasage: out -> msg */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_AssignmentRequest, rab_assignment_request); + + /* 'msg' has been generated, we cann now release the input 'out' */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, rab_assignment_request); + + if (!msg) + return -EINVAL; + if (msg->len > len) + return -EINVAL; + + memcpy(data, msg->data, msg->len); + rc = msg->len; + msgb_free(msg); + return rc; +} + +/* Decode a RAB-AssignmentResponse message down to request IEs. */ +int ranap_rab_ass_resp_decode(RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies, const uint8_t *data, + unsigned int len) +{ + int rc; + asn_dec_rval_t dec_ret; + RANAP_RANAP_PDU_t _ranap_pdu; + RANAP_RANAP_PDU_t *ranap_pdu = &_ranap_pdu; + + /* NOTE: The caller must take care of freeing the raB_SetupOrModifyList that is contained in the result using: + * ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedList, decoded.raB_SetupOrModifiedList); */ + + memset(ranap_pdu, 0, sizeof(*ranap_pdu)); + memset(rab_assignment_response_ies, 0, sizeof(*rab_assignment_response_ies)); + + /* Decode the RANAP PDU (outer shell) */ + dec_ret = aper_decode(NULL, &asn_DEF_RANAP_RANAP_PDU, (void **)&ranap_pdu, data, len, 0, 0); + if (dec_ret.code != RC_OK) { + RANAP_DEBUG("Error in RANAP ASN.1 decode\n"); + return -EINVAL; + } + + /* We expect this to be an outcome message */ + if (ranap_pdu->present != RANAP_RANAP_PDU_PR_outcome) { + RANAP_DEBUG("RAB AssignmentResponse does not contain an outcome message\n"); + rc = -EINVAL; + goto error; + } + + /* We expect the procedure code to match, this should always be the case since the procedure code is already + * matched by the code pathes before and we won't even attempt to enter this code path with a procedure code + * other then RANAP_ProcedureCode_id_RAB_Assignment */ + if (ranap_pdu->choice.initiatingMessage.procedureCode != RANAP_ProcedureCode_id_RAB_Assignment) { + RANAP_DEBUG("Procedure code indicates that this message is not a RAB Assignment!\n"); + rc = -EINVAL; + goto error; + } + + /* Decode RAB assignment response IEs (inner shell) */ + rc = ranap_decode_rab_assignmentresponseies(rab_assignment_response_ies, &ranap_pdu->choice.outcome.value); + if (rc != 0) { + RANAP_DEBUG("Unable to decode RAB AssignmentResponse IEs!\n"); + rc = -EINVAL; + goto error; + } + + rc = 0; +error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RANAP_PDU, ranap_pdu); + return rc; +} + +/* Encode a RAB-AssignmentResponse message from given request IEs. */ +int ranap_rab_ass_resp_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies) +{ + int rc; + struct msgb *msg; + + RANAP_RAB_AssignmentResponse_t _rab_assignment_response; + RANAP_RAB_AssignmentResponse_t *rab_assignment_response = &_rab_assignment_response; + memset(rab_assignment_response, 0, sizeof(*rab_assignment_response)); + + rc = ranap_encode_rab_assignmentresponseies(rab_assignment_response, rab_assignment_response_ies); + if (rc < 0) + return -EINVAL; + + /* generate an outcome mesasage: out -> msg */ + msg = ranap_generate_outcome(RANAP_ProcedureCode_id_RAB_Assignment, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_AssignmentResponse, rab_assignment_response); + + /* 'msg' has been generated, we cann now release the input 'out' */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentResponse, rab_assignment_response); + + if (!msg) + return -EINVAL; + if (msg->len > len) + return -EINVAL; + + memcpy(data, msg->data, msg->len); + rc = msg->len; + msgb_free(msg); + return rc; +} + +/* Pick the first item from the RAB setup-or-modify list and return the first protocol-ie-field-pair. This is based on + * the assumption that a PS call will only assign a signle RAB. This could be different for video calls and IMS but + * those are in practice a corner case, so we go for this simplified assumption for now. */ +static RANAP_ProtocolIE_FieldPair_t *prot_ie_field_pair_from_ass_req_ies(const RANAP_RAB_AssignmentRequestIEs_t *ies) +{ + RANAP_ProtocolIE_ContainerPair_t *protocol_ie_container_pair; + RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair; + + /* Make sure we indeed deal with a setup-or-modify list */ + if (!(ies->presenceMask & RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT)) { + RANAP_DEBUG + ("Decoding failed, the RANAP RAB AssignmentRequest did not contain a setup-or-modify list!\n"); + return NULL; + } + + protocol_ie_container_pair = ies->raB_SetupOrModifyList.list.array[0]; + protocol_ie_field_pair = protocol_ie_container_pair->list.array[0]; + + return protocol_ie_field_pair; +} + +/* See also comment above prot_ie_field_pair_from_ass_req_ies */ +static RANAP_IE_t *setup_or_modif_item_from_rab_ass_resp(const RANAP_RAB_AssignmentResponseIEs_t *ies) +{ + /* Make sure we indeed deal with a setup-or-modified list */ + if (!(ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_SETUPORMODIFIEDLIST_PRESENT)) { + RANAP_DEBUG + ("Decoding failed, the RANAP RAB AssignmentResponse did not contain a setup-or-modified list!\n"); + return NULL; + } + + return ies->raB_SetupOrModifiedList.raB_SetupOrModifiedList_ies.list.array[0]; +} + +/*! Extract IP address and port from the transport-layer-address that is contained inside RAB AssignmentRequest. + * \ptmap[out] addr buffer to store extracted RTP stream IP address (length at least INET6_ADDRSTRLEN). + * \ptmap[out] port pointer to store extracted RTP stream IP port number (host byte order). + * \ptmap[out] rab_id pointer to store RAB-ID (optional, can be NULL). + * \ptmap[in] data buffer with ASN.1 encoded message. + * \ptmap[in] data_len length of buffer with ASN.1 encoded message. + * \returns 0 on success; negative on error. */ +int ranap_rab_ass_req_extract_inet_addr(char *addr, uint16_t *port, uint8_t *rab_id, const uint8_t *data, + unsigned int data_len) +{ + RANAP_RAB_AssignmentRequestIEs_t _rab_assignment_request_ies; + RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies = &_rab_assignment_request_ies; + RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair; + RANAP_RAB_SetupOrModifyItemFirst_t _rab_setup_or_modify_item_first; + RANAP_RAB_SetupOrModifyItemFirst_t *rab_setup_or_modify_item_first = &_rab_setup_or_modify_item_first; + int rc; + + rc = ranap_rab_ass_req_decode(rab_assignment_request_ies, data, data_len); + if (rc < 0) + return -EINVAL; + + protocol_ie_field_pair = prot_ie_field_pair_from_ass_req_ies(rab_assignment_request_ies); + if (!protocol_ie_field_pair) { + rc = -EINVAL; + goto early_error; + } + + if (protocol_ie_field_pair->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem) { + RANAP_DEBUG + ("Decoding failed, the protocol IE field-pair is not of type RANAP RAB setup-or-modify-item!\n"); + rc = -EINVAL; + goto early_error; + } + + rc = ranap_decode_rab_setupormodifyitemfirst(rab_setup_or_modify_item_first, + &protocol_ie_field_pair->firstValue); + if (rc < 0) { + rc = -EINVAL; + goto early_error; + } + + if (rab_id) { + /* The RAB-ID is defined as a bitstring with a size of 8 (1 byte), + * See also RANAP-IEs.asn, RAB-ID ::= BIT STRING (SIZE (8)) */ + *rab_id = rab_setup_or_modify_item_first->rAB_ID.buf[0]; + } + + rc = ranap_transp_layer_addr_decode(addr, INET6_ADDRSTRLEN, + &rab_setup_or_modify_item_first->transportLayerInformation-> + transportLayerAddress); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + rc = ranap_transp_assoc_decode(port, + &rab_setup_or_modify_item_first->transportLayerInformation-> + iuTransportAssociation); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + rc = 0; +error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, rab_setup_or_modify_item_first); +early_error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList, + &rab_assignment_request_ies->raB_SetupOrModifyList); + return rc; +} + +/*! Extract IP address and port from the transport-layer-address that is contained inside RAB AssignmentResponse. + * \ptmap[out] addr buffer to store extracted RTP stream IP address (length at least INET6_ADDRSTRLEN). + * \ptmap[out] port pointer to store extracted RTP stream IP port number (host byte order). + * \ptmap[in] data buffer with ASN.1 encoded message. + * \ptmap[in] data_len length of buffer with ASN.1 encoded message. + * \returns 0 on success; negative on error. */ +int ranap_rab_ass_resp_extract_inet_addr(char *addr, uint16_t *port, const uint8_t *data, unsigned int data_len) +{ + RANAP_RAB_AssignmentResponseIEs_t _rab_assignment_response_ies; + RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies = &_rab_assignment_response_ies; + RANAP_IE_t *setup_or_modified_list_ie; + RANAP_RAB_SetupOrModifiedItemIEs_t _rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItemIEs_t *rab_setup_or_modified_items_ies = &_rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItem_t *rab_setup_or_modified_item; + int rc; + + rc = ranap_rab_ass_resp_decode(rab_assignment_response_ies, data, data_len); + if (rc < 0) + return -EINVAL; + + setup_or_modified_list_ie = setup_or_modif_item_from_rab_ass_resp(rab_assignment_response_ies); + if (!setup_or_modified_list_ie) { + rc = -EINVAL; + goto early_error; + } + + rc = ranap_decode_rab_setupormodifieditemies_fromlist(rab_setup_or_modified_items_ies, + &setup_or_modified_list_ie->value); + if (rc < 0) { + rc = -EINVAL; + goto early_error; + } + + rab_setup_or_modified_item = &rab_setup_or_modified_items_ies->raB_SetupOrModifiedItem; + + rc = ranap_transp_layer_addr_decode(addr, INET6_ADDRSTRLEN, rab_setup_or_modified_item->transportLayerAddress); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + rc = ranap_transp_assoc_decode(port, rab_setup_or_modified_item->iuTransportAssociation); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + rc = 0; +error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedItem, rab_setup_or_modified_items_ies); +early_error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedList, + &rab_assignment_response_ies->raB_SetupOrModifiedList); + return rc; +} + +/*! Replace IP address and port in the transport-layer-address that is contained inside RAB AssignmentRequest. + * \ptmap[inout] data buffer with ASN.1 encoded message. + * \ptmap[in] data_len length of buffer with ASN.1 encoded message. + * \ptmap[in] addr buffer that contains the new RTP stream IP address. + * \ptmap[in] port new RTP stream IP port number (host byte order). + * \returns resulting message length on success; negative on error. */ +int ranap_rab_ass_req_replace_inet_addr(uint8_t *data, unsigned int data_len, const char *addr, uint32_t port) +{ + + /* FIXME: WHAT IF THE RESULTING LENGTH OF THE MESSAGE IS DIFFERENT!? */ + RANAP_RAB_AssignmentRequestIEs_t _rab_assignment_request_ies; + RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies = &_rab_assignment_request_ies; + RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair; + RANAP_RAB_SetupOrModifyItemFirst_t _rab_setup_or_modify_item_first; + RANAP_RAB_SetupOrModifyItemFirst_t *rab_setup_or_modify_item_first = &_rab_setup_or_modify_item_first; + struct osmo_sockaddr ip_addr; + struct osmo_sockaddr_str sockaddr_str; + RANAP_TransportLayerInformation_t *old_transport_layer_information = NULL; + RANAP_TransportLayerInformation_t *new_transport_layer_information = NULL; + int rc; + + rc = ranap_rab_ass_req_decode(rab_assignment_request_ies, data, data_len); + if (rc < 0) + return -EINVAL; + + protocol_ie_field_pair = prot_ie_field_pair_from_ass_req_ies(rab_assignment_request_ies); + if (!protocol_ie_field_pair) { + rc = -EINVAL; + goto early_error; + } + + if (protocol_ie_field_pair->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem) { + RANAP_DEBUG("Rewriting transport layer information failed, unexpected IE field-pair type!\n"); + rc = -EINVAL; + goto early_error; + } + + /* Decode setup-or-modifiy item (first) */ + rc = ranap_decode_rab_setupormodifyitemfirst(rab_setup_or_modify_item_first, + &protocol_ie_field_pair->firstValue); + if (rc < 0) { + rc = -EINVAL; + goto early_error; + } + + /* Replace transport-layer-information */ + if (rab_setup_or_modify_item_first->transportLayerInformation->iuTransportAssociation.present == + RANAP_IuTransportAssociation_PR_bindingID) { + sockaddr_str = (struct osmo_sockaddr_str) { + .af = AF_INET, + .port = port, + }; + osmo_strlcpy(sockaddr_str.ip, addr, INET6_ADDRSTRLEN); + + rc = osmo_sockaddr_str_to_sockaddr(&sockaddr_str, &ip_addr.u.sas); + if (rc < 0) { + RANAP_DEBUG("Rewriting transport layer information failed, invalid address!\n"); + rc = -EINVAL; + goto error; + } + + old_transport_layer_information = rab_setup_or_modify_item_first->transportLayerInformation; + new_transport_layer_information = ranap_new_transp_info_rtp(&ip_addr, true); //<============= FIXME! + OSMO_ASSERT(new_transport_layer_information); + rab_setup_or_modify_item_first->transportLayerInformation = new_transport_layer_information; + } else { + RANAP_DEBUG("Rewriting transport layer information failed, no bindingID (port)!\n"); + rc = -EINVAL; + goto error; + } + + /* Reencode transport-layer-information */ + rc = ANY_fromType_aper(&protocol_ie_field_pair->firstValue, &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, + rab_setup_or_modify_item_first); + if (rc < 0) { + RANAP_DEBUG("Rewriting transport layer information failed, could not reencode\n"); + rc = -EINVAL; + goto error; + } + + /* Do the final encoding */ + rc = ranap_rab_ass_req_encode(data, data_len, rab_assignment_request_ies); + if (rc < 0) + rc = -EINVAL; + +error: + /* Restore original state of the modified ASN.1 struct so that the asn1c free mechanisms can work properly */ + if (old_transport_layer_information) + rab_setup_or_modify_item_first->transportLayerInformation = old_transport_layer_information; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, rab_setup_or_modify_item_first); + if (new_transport_layer_information) + ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, new_transport_layer_information); +early_error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList, + &rab_assignment_request_ies->raB_SetupOrModifyList); + return rc; +} + +/*! Replace IP address and port in the transport-layer-address that is contained inside RAB AssignmentResponse. + * \ptmap[inout] data buffer with ASN.1 encoded message. + * \ptmap[in] data_len length of buffer with ASN.1 encoded message. + * \ptmap[in] addr buffer that contains the new RTP stream IP address. + * \ptmap[in] port new RTP stream IP port number (host byte order). + * \returns resulting message length on success; negative on error. */ +int ranap_rab_ass_resp_replace_inet_addr(uint8_t *data, unsigned int data_len, const char *addr, uint32_t port) +{ + RANAP_RAB_AssignmentResponseIEs_t _rab_assignment_response_ies; + RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies = &_rab_assignment_response_ies; + RANAP_IE_t *setup_or_modified_list_ie; + RANAP_RAB_SetupOrModifiedItemIEs_t _rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItemIEs_t *rab_setup_or_modified_items_ies = &_rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItem_t *rab_setup_or_modified_item; + RANAP_TransportLayerInformation_t *temp_transport_layer_information = NULL; + RANAP_TransportLayerAddress_t *old_transport_layer_address = NULL; + RANAP_IuTransportAssociation_t *old_iu_transport_association = NULL; + struct osmo_sockaddr ip_addr; + struct osmo_sockaddr_str sockaddr_str; + int rc; + + rc = ranap_rab_ass_resp_decode(rab_assignment_response_ies, data, data_len); + if (rc < 0) + return -EINVAL; + + setup_or_modified_list_ie = setup_or_modif_item_from_rab_ass_resp(rab_assignment_response_ies); + if (!setup_or_modified_list_ie) { + rc = -EINVAL; + goto early_error; + } + + rc = ranap_decode_rab_setupormodifieditemies_fromlist(rab_setup_or_modified_items_ies, + &setup_or_modified_list_ie->value); + if (rc < 0) { + rc = -EINVAL; + goto early_error; + } + + rab_setup_or_modified_item = &rab_setup_or_modified_items_ies->raB_SetupOrModifiedItem; + + /* Generate a temporary transport layer information, from which we can use the transport layer address and + * the iu transport association to update the setup or modified item */ + sockaddr_str = (struct osmo_sockaddr_str) { + .af = AF_INET, + .port = port, + }; + osmo_strlcpy(sockaddr_str.ip, addr, INET6_ADDRSTRLEN); + rc = osmo_sockaddr_str_to_sockaddr(&sockaddr_str, &ip_addr.u.sas); + if (rc < 0) { + RANAP_DEBUG("Rewriting transport layer address failed, invalid address!\n"); + rc = -EINVAL; + goto error; + } + temp_transport_layer_information = ranap_new_transp_info_rtp(&ip_addr, true); //<============= FIXME! + OSMO_ASSERT(temp_transport_layer_information); + + /* Replace transport layer address and iu transport association */ + old_transport_layer_address = rab_setup_or_modified_item->transportLayerAddress; + old_iu_transport_association = rab_setup_or_modified_item->iuTransportAssociation; + rab_setup_or_modified_item->transportLayerAddress = &temp_transport_layer_information->transportLayerAddress; + rab_setup_or_modified_item->iuTransportAssociation = &temp_transport_layer_information->iuTransportAssociation; + + /* Reencode modified setup or modified list */ + rc = ANY_fromType_aper(&setup_or_modified_list_ie->value, &asn_DEF_RANAP_RAB_SetupOrModifiedItem, + rab_setup_or_modified_items_ies); + if (rc < 0) { + RANAP_DEBUG("Rewriting transport layer address failed, could not reencode\n"); + rc = -EINVAL; + goto error; + } + + /* Do the final encoding */ + rc = ranap_rab_ass_resp_encode(data, data_len, rab_assignment_response_ies); + if (rc < 0) + rc = -EINVAL; + +error: + /* Restore original state of the modified ASN.1 struct so that the asn1c free mechanisms can work properly */ + if (old_transport_layer_address) + rab_setup_or_modified_item->transportLayerAddress = old_transport_layer_address; + if (old_iu_transport_association) + rab_setup_or_modified_item->iuTransportAssociation = old_iu_transport_association; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedItem, rab_setup_or_modified_items_ies); + if (temp_transport_layer_information) + ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, temp_transport_layer_information); +early_error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedList, + &rab_assignment_response_ies->raB_SetupOrModifiedList); + return rc; +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 899e436..f9da51f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = \ + ranap_rab_ass \ $(NULL)
# The `:;' works around a Bash 3.2 bug when the output is not writeable. diff --git a/tests/test_common.c b/tests/test_common.c new file mode 100644 index 0000000..b9527c1 --- /dev/null +++ b/tests/test_common.c @@ -0,0 +1,111 @@ +/* Common osmo-iuh test stub code */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * Author: Daniel Willmann dwillmann@sysmocom.de + * 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 http://www.gnu.org/licenses/. + * + */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <errno.h> +#include <signal.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/sctp.h> +#include <arpa/inet.h> + +#include <osmocom/core/application.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/logging.h> + +#include <osmocom/ranap/ranap_common.h> + +#include <osmocom/hnbgw/hnbgw.h> + +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", + }, + [DRANAP] = { + .name = "RANAP", .loglevel = LOGL_DEBUG, .enabled = 1, + .color = "", + .description = "RAN Application Part", + }, + [DRUA] = { + .name = "RUA", .loglevel = LOGL_DEBUG, .enabled = 1, + .color = "", + .description = "RANAP User Adaptation", + }, +}; + +static const struct log_info test_log_info = { + .cat = log_cat, + .num_cat = ARRAY_SIZE(log_cat), +}; + +static void *msgb_ctx; + +int test_common_init(void) +{ + int rc; + + msgb_ctx = msgb_talloc_ctx_init(NULL, 0); + talloc_asn1_ctx = talloc_named_const(NULL, 0, "asn1_context"); + + rc = osmo_init_logging(&test_log_info); + if (rc < 0) + exit(1); + + ranap_set_log_area(DRANAP); + + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 0); + log_set_print_category_hex(osmo_stderr_target, 0); + return rc; +} + +void test_common_cleanup(void) +{ + if (talloc_total_blocks(msgb_ctx) != 1 + || talloc_total_size(msgb_ctx) != 0) + talloc_report_full(msgb_ctx, stderr); + + OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1); + OSMO_ASSERT(talloc_total_size(msgb_ctx) == 0); + talloc_free(msgb_ctx); + + if (talloc_total_blocks(talloc_asn1_ctx) != 1 + || talloc_total_size(talloc_asn1_ctx) != 0) + talloc_report_full(talloc_asn1_ctx, stderr); + + OSMO_ASSERT(talloc_total_blocks(talloc_asn1_ctx) == 1); + OSMO_ASSERT(talloc_total_size(talloc_asn1_ctx) == 0); + talloc_free(talloc_asn1_ctx); +} diff --git a/tests/test_common.h b/tests/test_common.h new file mode 100644 index 0000000..836d999 --- /dev/null +++ b/tests/test_common.h @@ -0,0 +1,4 @@ +#pragma once + +int test_common_init(void); +void test_common_cleanup(void); diff --git a/tests/testsuite.at b/tests/testsuite.at index 65d1ca0..41d0449 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,8 +1,9 @@ AT_INIT AT_BANNER([Regression tests.])
-#AT_SETUP([foobar]) -#AT_KEYWORDS([foobar]) -#cat $abs_srcdir/foobar/foobar_test.ok > expout -#AT_CHECK([$abs_top_builddir/tests/foobar/foobar_test], [], [expout], [ignore]) -#AT_CLEANUP +AT_SETUP([ranap-rab-ass]) +AT_KEYWORDS([ranap-rab-ass]) +cat $abs_srcdir/ranap_rab_ass/ranap_rab_ass_test.ok > expout +cat $abs_srcdir/ranap_rab_ass/ranap_rab_ass_test.err > experr +AT_CHECK([$abs_top_builddir/tests/ranap_rab_ass/ranap_rab_ass_test], [0], [expout], [experr]) +AT_CLEANUP \ No newline at end of file
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 1:
(2 comments)
This is not fully finished yet. As suggested I will make the functions AF agnostic as well and fix the X213 NSAP problem.
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/1/src/osmo-hnbgw/ranap_rab_a... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/1/src/osmo-hnbgw/ranap_rab_a... PS1, Line 473: int ranap_rab_ass_resp_replace_inet_addr(uint8_t *data, unsigned int data_len, const char *addr, uint32_t port)
why passing the addr here is string format? I'd make more sense to pass a osmo_sockaddr.
Yes, its probably a good idea to make this functions also AF agnostic.
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/1/src/osmo-hnbgw/ranap_rab_a... PS1, Line 520: temp_transport_layer_information = ranap_new_transp_info_rtp(&ip_addr, true); //<============= FIXME!
what about this?
This is not ready yet. We need to determine the address encoding and retain it. This converts everything to X.213 NSAP, which is not correct.
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 2:
I have now fixed the problem with the address encoding method. Also the ranap_rab_ass functions are all AF agnostic. This means in theory this would support IPv6 now.
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#3).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.err A tests/ranap_rab_ass/ranap_rab_ass_test.ok A tests/test_common.c A tests/test_common.h M tests/testsuite.at 12 files changed, 1,056 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/3
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#4).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.err A tests/ranap_rab_ass/ranap_rab_ass_test.ok A tests/test_common.c A tests/test_common.h M tests/testsuite.at 12 files changed, 1,054 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/4
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#5).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.err A tests/ranap_rab_ass/ranap_rab_ass_test.ok A tests/test_common.c A tests/test_common.h M tests/testsuite.at 12 files changed, 1,056 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/5
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#6).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok A tests/test_common.c A tests/test_common.h M tests/testsuite.at 11 files changed, 1,037 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/6
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#7).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok A tests/test_common.c A tests/test_common.h M tests/testsuite.at 11 files changed, 1,036 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/7
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#8).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok A tests/test_common.c A tests/test_common.h M tests/testsuite.at 11 files changed, 1,038 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/8
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#9).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 9 files changed, 975 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/9
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#10).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 977 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/10
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#11).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 980 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/11
laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 11:
(1 comment)
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/11/src/osmo-hnbgw/ranap_rab_... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/11/src/osmo-hnbgw/ranap_rab_... PS11, Line 34: int ranap_rab_ass_req_decode(RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies, const uint8_t *data, I'm a bit surprised that we pass the binary PDU in here and then deocde it, but only return a very small subset of the message.
Isn't the normal approach to do this in a generic fashion? Shouldn't the caller already have done a aper_decode of the ranap_pdu before the caller can know us? If so, then the input data to this function would not be the 'const uitn8_t *data' but already the 'const RANAP_RANAP_PDU_t *' ?
Or even more generic: shouldn't all of the code operate on the 'typedef struct ranap_message_s ... ranap_message'?
Something like ranap_common_cn.c (but this one only handles the messages received in the uplink direction)? Then there would be one decoder function to call, which recursively decodes all information elements. The result is stored in a ranap_message. Then there is a functio nthat handles this decoded message.
That's how we implement the entire handling of the MSC and SGSN code. I'm wondering why you're not doing the same here?
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#13).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 891 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/13
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 13:
(1 comment)
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/11/src/osmo-hnbgw/ranap_rab_... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/11/src/osmo-hnbgw/ranap_rab_... PS11, Line 34: int ranap_rab_ass_req_decode(RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies, const uint8_t *data,
I'm a bit surprised that we pass the binary PDU in here and then deocde it, but only return a very s […]
My main concern here was to lower the risk to introduce memory leaks. So I wanted to keep only the binary representations and not the ASN.1 decoded representations which are nested multiple times and therefore have a lot of memory to manage.
However, I also think its better to do the aper_decode() outside of these helper functions to get the procedure code first. I have changed the functions now so that they take a RANAP_RANAP_PDU_t. I still think that it is the best when all the remaining nested encoding/decoding happens inside of those helper functions.
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#14).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Depends: osmo-iuh.git Id7293c1035cf6de34b7a416fa9265a5a32ed3216 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 891 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/14
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 14:
(1 comment)
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu) Why not passing RANAP_RAB_AssignmentRequestIEs_t here instead of RANAP_RANAP_PDU_t?
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
Why not passing RANAP_RAB_AssignmentRequestIEs_t here instead of RANAP_RANAP_PDU_t?
That is possible, but then the usage of those functions get more complicated as caller then has to take care about the decoding and of course the freeing of the memory afterwards.
What advantage do you see?
Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#15).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 891 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/15
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
That is possible, but then the usage of those functions get more complicated as caller then has to t […]
Not having to decode the same message N times.
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/14/src/osmo-hnbgw/ranap_rab_... PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
Not having to decode the same message N times.
Its actually two times at the moment for each messages at the moment. If we do the encoding/decoding of the RANAP PDU externally we could save 2 decodings. Is ASN.1 decoding so expensive that we have to optimize on this? However, I have the feeling that it may make sense to split it off as you suggested. When we work with multiple RABs one day we might benefit from a more open model.
Attention is currently required from: pespin, dexter. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/comment/3974a6ae_911c1f01 PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
Its actually two times at the moment for each messages at the moment. […]
As I stated, the best would likely be to use ranap_message which is an overall container for the RANAP message and all of its contents.
I would expect the ASN.1 decode is among the more expensive things that osmo-hnbgw does. However, performance is likely irrelevant in the kind of deployments we are looking at, where we have a few hundred hNB. Remember, it is control plane processing only.
To me it's more a question of code maintainability and KISS, performance is not super-critical.
We do have a relatively well-established way how to deal with ranap_message in the SGSN and MSC, so why should we deviate from this existing pattern here?
Attention is currently required from: laforge, pespin. dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/comment/a1fb5259_7ac9e0c0 PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
As I stated, the best would likely be to use ranap_message which is an overall container for the RAN […]
When I understand the implementation correctly we only have decoders for the RNC->CN direction yet. (ranap_common_cn.c). This means using the ranap_cn_rx_co() for decoding messages from the RNC would already work. What we do not have yet is a counterpart that can decode CN->RNC messages. We basically need a ranap_common_rnc.c that works the same way as ranap_common_cn.c. At the moment we would only implement the path for the RAB AssignmentRequest (Initiating Message).
I would now start using ranap_common_cn.c for the RAB AssignmentResponse as there the decoder already exist and then implement the decoders and use them for RAB AssignmentRequest.
Attention is currently required from: laforge, pespin. dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/comment/129cc62e_0d60709e PS11, Line 34: int ranap_rab_ass_req_decode(RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies, const uint8_t *data,
My main concern here was to lower the risk to introduce memory leaks. […]
given that there are
RANAP_RAB_AssignmentRequestIEs_t raB_AssignmentRequestIEs; RANAP_RAB_AssignmentResponseIEs_t raB_AssignmentResponseIEs;
in ranap_message, it probably makes sense to use those instead of RANAP_RANAP_PDU_t as input/output for the helper functions.
What I haven't seen so far is an encoder that does the same as ranap_common_cn.c in reverse.
Attention is currently required from: pespin, dexter. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 15:
(1 comment)
File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/comment/ea4e7f5f_800e9ce6 PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
When I understand the implementation correctly we only have decoders for the RNC->CN direction yet. […]
yes, I think this sounds good. Add only the decoder[s] we need to ranap_common*.c and then use them from hnbgw.
Attention is currently required from: pespin, dexter. Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#16).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 865 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/16
Attention is currently required from: pespin. dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 16:
(1 comment)
Patchset:
PS16: This is not finished yet. There is still some stuff to cleanup and there is also the following problem:
At the moment we use ranap_cn_rx_co and ranap_ran_rx_co as decoders. Those functions take a callback that is called with the decoded ranap_message container, but when the callback is done the ranap_message is freed again. It works fine that way, but this API is very clumsy to use. I have looked at ranap_cn_rx_co and I think it is possible to add a ranap_cn_rx_co_decode() and ranap_cn_rx_co_free() that give the user direct access to the ranap_message container. This would give us a lot more flexibility. We could do the decode once when the RAB Assignment Request/Response is intercepted and do the free when the FSM is cleaned up. This also saves us the additional decode we would need when we check the Procedure code. So that would be the next step, adding the _free and _decode functions to osmo_iuh and then using them here.
Attention is currently required from: laforge, pespin. dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 17:
(2 comments)
File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/comment/25f0f1e7_59363af3 PS11, Line 34: int ranap_rab_ass_req_decode(RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies, const uint8_t *data,
given that there are […]
Done
File src/osmo-hnbgw/ranap_rab_ass.c:
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792/comment/3b22ff36_af7d24b9 PS14, Line 198: int ranap_rab_ass_req_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, RANAP_RANAP_PDU_t *ranap_pdu)
yes, I think this sounds good. Add only the decoder[s] we need to ranap_common*. […]
Done
Attention is currently required from: laforge, pespin. Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#17).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 841 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/17
Attention is currently required from: laforge, pespin, dexter. Hello osmith, Jenkins Builder, pespin, daniel,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
to look at the new patch set (#18).
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 841 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/92/26792/18
Attention is currently required from: pespin, dexter. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 18: Code-Review+1
Attention is currently required from: pespin, dexter. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
Patch Set 18: Code-Review+2
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792 )
Change subject: ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response ......................................................................
ranap_rab_ass: add decoder and rewrite functions for RAB-AssignmentRequest/Response
The RANAP RAB AssignmentRequest and AssignmentResponse contains the IP-Address and the IP-Port for the RTP voice stream. In the comming MGCP implementation we will have to extract and replace this information. Lets add functions that do that in a convinient way.
Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837 Related: OS#5152 --- M configure.ac M include/osmocom/hnbgw/Makefile.am A include/osmocom/hnbgw/ranap_rab_ass.h M src/osmo-hnbgw/Makefile.am A src/osmo-hnbgw/ranap_rab_ass.c M tests/Makefile.am A tests/ranap_rab_ass/Makefile.am A tests/ranap_rab_ass/ranap_rab_ass_test.c A tests/ranap_rab_ass/ranap_rab_ass_test.ok M tests/testsuite.at 10 files changed, 841 insertions(+), 6 deletions(-)
Approvals: Jenkins Builder: Verified laforge: Looks good to me, approved
diff --git a/configure.ac b/configure.ac index a88ff42..520cd68 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,7 @@ src/osmo-hnbgw/Makefile tests/Makefile tests/atlocal + tests/ranap_rab_ass/Makefile doc/Makefile doc/examples/Makefile doc/manuals/Makefile diff --git a/include/osmocom/hnbgw/Makefile.am b/include/osmocom/hnbgw/Makefile.am index b2a667d..0ddd42e 100644 --- a/include/osmocom/hnbgw/Makefile.am +++ b/include/osmocom/hnbgw/Makefile.am @@ -1,4 +1,5 @@ noinst_HEADERS = \ vty.h \ context_map.h hnbgw.h hnbgw_cn.h \ - hnbgw_hnbap.h hnbgw_rua.h hnbgw_ranap.h + hnbgw_hnbap.h hnbgw_rua.h hnbgw_ranap.h \ + ranap_rab_ass.h diff --git a/include/osmocom/hnbgw/ranap_rab_ass.h b/include/osmocom/hnbgw/ranap_rab_ass.h new file mode 100644 index 0000000..4cb8e37 --- /dev/null +++ b/include/osmocom/hnbgw/ranap_rab_ass.h @@ -0,0 +1,13 @@ +#pragma once + +int ranap_rab_ass_req_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies); +int ranap_rab_ass_resp_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies); + +int ranap_rab_ass_req_ies_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, + RANAP_RAB_AssignmentRequestIEs_t *ies); +int ranap_rab_ass_resp_ies_extract_inet_addr(struct osmo_sockaddr *addr, RANAP_RAB_AssignmentResponseIEs_t *ies); + +int ranap_rab_ass_req_ies_replace_inet_addr(RANAP_RAB_AssignmentRequestIEs_t *ies, struct osmo_sockaddr *addr); +int ranap_rab_ass_resp_ies_replace_inet_addr(RANAP_RAB_AssignmentResponseIEs_t *ies, struct osmo_sockaddr *addr); diff --git a/src/osmo-hnbgw/Makefile.am b/src/osmo-hnbgw/Makefile.am index bda8633..0948170 100644 --- a/src/osmo-hnbgw/Makefile.am +++ b/src/osmo-hnbgw/Makefile.am @@ -37,6 +37,7 @@ hnbgw_vty.c \ context_map.c \ hnbgw_cn.c \ + ranap_rab_ass.c \ $(NULL)
osmo_hnbgw_LDADD = \ diff --git a/src/osmo-hnbgw/ranap_rab_ass.c b/src/osmo-hnbgw/ranap_rab_ass.c new file mode 100644 index 0000000..f5d86a1 --- /dev/null +++ b/src/osmo-hnbgw/ranap_rab_ass.c @@ -0,0 +1,425 @@ +/* (C) 2021 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * All Rights Reserved + * + * Author: Philipp Maier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +/* Note: This files contains tools to decode and re-encode the RAB-AssignmentRequest. This set of tools is used by + * mgcp_fsm.c to extract and manipulate the transportLayerAddress. */ + +#include <errno.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/ranap/ranap_common.h> +#include <osmocom/ranap/ranap_common_cn.h> +#include <osmocom/ranap/ranap_common_ran.h> +#include <osmocom/ranap/iu_helpers.h> +#include <asn1c/asn1helpers.h> + +/*! Encode RABAP RAB AssignmentRequest from RANAP_RAB_AssignmentRequestIEs. + * \ptmap[out] data user provided memory to store resulting ASN.1 encoded message. + * \ptmap[in] len length of user provided memory to store resulting ASN.1 encoded message. + * \ptmap[in] ies user provided memory with RANAP_RAB_AssignmentRequestIEs. + * \returns resulting message length on success; negative on error. */ +int ranap_rab_ass_req_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentRequestIEs_t *rab_assignment_request_ies) +{ + int rc; + struct msgb *msg; + RANAP_RAB_AssignmentRequest_t _rab_assignment_request; + RANAP_RAB_AssignmentRequest_t *rab_assignment_request = &_rab_assignment_request; + + memset(data, 0, len); + memset(rab_assignment_request, 0, sizeof(*rab_assignment_request)); + + rc = ranap_encode_rab_assignmentrequesties(rab_assignment_request, rab_assignment_request_ies); + if (rc < 0) + return -EINVAL; + + /* generate an Initiating Mesasage */ + msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_AssignmentRequest, rab_assignment_request); + + /* 'msg' has been generated, we cann now release the input 'out' */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, rab_assignment_request); + + if (!msg) + return -EINVAL; + if (msg->len > len) + return -EINVAL; + + memcpy(data, msg->data, msg->len); + rc = msg->len; + msgb_free(msg); + return rc; +} + +/*! Encode RABAP RAB AssignmentRequest from RANAP_RAB_AssignmentResponseIEs. + * \ptmap[out] data user provided memory to store resulting ASN.1 encoded message. + * \ptmap[in] len length of user provided memory to store resulting ASN.1 encoded message. + * \ptmap[in] ies user provided memory with RANAP_RAB_AssignmentResponseIEs. + * \returns resulting message length on success; negative on error. */ +int ranap_rab_ass_resp_encode(uint8_t *data, unsigned int len, + RANAP_RAB_AssignmentResponseIEs_t *rab_assignment_response_ies) +{ + int rc; + struct msgb *msg; + + RANAP_RAB_AssignmentResponse_t _rab_assignment_response; + RANAP_RAB_AssignmentResponse_t *rab_assignment_response = &_rab_assignment_response; + + memset(data, 0, len); + memset(rab_assignment_response, 0, sizeof(*rab_assignment_response)); + + rc = ranap_encode_rab_assignmentresponseies(rab_assignment_response, rab_assignment_response_ies); + if (rc < 0) + return -EINVAL; + + /* generate an outcome mesasage */ + msg = ranap_generate_outcome(RANAP_ProcedureCode_id_RAB_Assignment, + RANAP_Criticality_reject, + &asn_DEF_RANAP_RAB_AssignmentResponse, rab_assignment_response); + + /* 'msg' has been generated, we cann now release the input 'out' */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentResponse, rab_assignment_response); + + if (!msg) + return -EINVAL; + if (msg->len > len) + return -EINVAL; + + memcpy(data, msg->data, msg->len); + rc = msg->len; + msgb_free(msg); + return rc; +} + +/* Pick the first item from the RAB setup-or-modify list and return the first protocol-ie-field-pair. This is based on + * the assumption that a PS call will only assign a signle RAB. This could be different for video calls and IMS but + * those are in practice a corner case, so we go for this simplified assumption for now. */ +static RANAP_ProtocolIE_FieldPair_t *prot_ie_field_pair_from_ass_req_ies(const RANAP_RAB_AssignmentRequestIEs_t *ies) +{ + RANAP_ProtocolIE_ContainerPair_t *protocol_ie_container_pair; + RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair; + + /* Make sure we indeed deal with a setup-or-modify list */ + if (!(ies->presenceMask & RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT)) { + RANAP_DEBUG + ("Decoding failed, the RANAP RAB AssignmentRequest did not contain a setup-or-modify list!\n"); + return NULL; + } + + protocol_ie_container_pair = ies->raB_SetupOrModifyList.list.array[0]; + protocol_ie_field_pair = protocol_ie_container_pair->list.array[0]; + + return protocol_ie_field_pair; +} + +/* See also comment above prot_ie_field_pair_from_ass_req_ies */ +static RANAP_IE_t *setup_or_modif_item_from_rab_ass_resp(const RANAP_RAB_AssignmentResponseIEs_t *ies) +{ + /* Make sure we indeed deal with a setup-or-modified list */ + if (!(ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_SETUPORMODIFIEDLIST_PRESENT)) { + RANAP_DEBUG + ("Decoding failed, the RANAP RAB AssignmentResponse did not contain a setup-or-modified list!\n"); + return NULL; + } + + return ies->raB_SetupOrModifiedList.raB_SetupOrModifiedList_ies.list.array[0]; +} + +/*! Extract IP address and port from RANAP_RAB_AssignmentRequestIEs. + * \ptmap[out] addr user provided memory to store extracted RTP stream IP-Address and port number. + * \ptmap[out] rab_id pointer to store RAB-ID (optional, can be NULL). + * \ptmap[in] ies user provided memory with RANAP_RAB_AssignmentRequestIEs. + * \returns 0 on success; negative on error. */ +int ranap_rab_ass_req_ies_extract_inet_addr(struct osmo_sockaddr *addr, uint8_t *rab_id, + RANAP_RAB_AssignmentRequestIEs_t *ies) +{ + RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair; + RANAP_RAB_SetupOrModifyItemFirst_t _rab_setup_or_modify_item_first; + RANAP_RAB_SetupOrModifyItemFirst_t *rab_setup_or_modify_item_first = &_rab_setup_or_modify_item_first; + RANAP_TransportLayerAddress_t *trasp_layer_addr; + RANAP_IuTransportAssociation_t *transp_assoc; + uint16_t port; + int rc; + + protocol_ie_field_pair = prot_ie_field_pair_from_ass_req_ies(ies); + if (!protocol_ie_field_pair) + return -EINVAL; + + if (protocol_ie_field_pair->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem) { + RANAP_DEBUG + ("Decoding failed, the protocol IE field-pair is not of type RANAP RAB setup-or-modify-item!\n"); + return -EINVAL; + } + + rc = ranap_decode_rab_setupormodifyitemfirst(rab_setup_or_modify_item_first, + &protocol_ie_field_pair->firstValue); + if (rc < 0) + return -EINVAL; + + if (rab_id) { + /* The RAB-ID is defined as a bitstring with a size of 8 (1 byte), + * See also RANAP-IEs.asn, RAB-ID ::= BIT STRING (SIZE (8)) */ + *rab_id = rab_setup_or_modify_item_first->rAB_ID.buf[0]; + } + + /* Decode IP-Address */ + trasp_layer_addr = &rab_setup_or_modify_item_first->transportLayerInformation->transportLayerAddress; + rc = ranap_transp_layer_addr_decode2(addr, NULL, trasp_layer_addr); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + /* Decode port number */ + transp_assoc = &rab_setup_or_modify_item_first->transportLayerInformation->iuTransportAssociation; + rc = ranap_transp_assoc_decode(&port, transp_assoc); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + switch (addr->u.sin.sin_family) { + case AF_INET: + addr->u.sin.sin_port = htons(port); + break; + case AF_INET6: + addr->u.sin6.sin6_port = htons(port); + break; + default: + rc = -EINVAL; + goto error; + } + + rc = 0; +error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, rab_setup_or_modify_item_first); + return rc; +} + +/*! Extract IP address and port from RANAP_RAB_AssignmentResponseIEs. + * \ptmap[out] addr user provided memory to store extracted RTP stream IP-Address and port number. + * \ptmap[in] ies user provided memory with RANAP_RAB_AssignmentResponseIEs. + * \returns 0 on success; negative on error. */ +int ranap_rab_ass_resp_ies_extract_inet_addr(struct osmo_sockaddr *addr, RANAP_RAB_AssignmentResponseIEs_t *ies) +{ + RANAP_IE_t *setup_or_modified_list_ie; + RANAP_RAB_SetupOrModifiedItemIEs_t _rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItemIEs_t *rab_setup_or_modified_items_ies = &_rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItem_t *rab_setup_or_modified_item; + uint16_t port; + int rc; + + setup_or_modified_list_ie = setup_or_modif_item_from_rab_ass_resp(ies); + if (!setup_or_modified_list_ie) + return -EINVAL; + + rc = ranap_decode_rab_setupormodifieditemies_fromlist(rab_setup_or_modified_items_ies, + &setup_or_modified_list_ie->value); + if (rc < 0) { + return -EINVAL; + } + + rab_setup_or_modified_item = &rab_setup_or_modified_items_ies->raB_SetupOrModifiedItem; + + /* Decode IP-Address */ + rc = ranap_transp_layer_addr_decode2(addr, NULL, rab_setup_or_modified_item->transportLayerAddress); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + /* Decode port number */ + rc = ranap_transp_assoc_decode(&port, rab_setup_or_modified_item->iuTransportAssociation); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + switch (addr->u.sin.sin_family) { + case AF_INET: + addr->u.sin.sin_port = htons(port); + break; + case AF_INET6: + addr->u.sin6.sin6_port = htons(port); + break; + default: + rc = -EINVAL; + goto error; + } + + rc = 0; +error: + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedItem, rab_setup_or_modified_items_ies); + return rc; +} + +/*! Replace IP address and port in RANAP_RAB_AssignmentRequestIEs. + * \ptmap[inout] ies user provided memory with RANAP_RAB_AssignmentRequestIEs. + * \ptmap[in] addr user provided memory that contains the new RTP stream IP-Address and port number. + * \returns 0 on success; negative on error. */ +int ranap_rab_ass_req_ies_replace_inet_addr(RANAP_RAB_AssignmentRequestIEs_t *ies, struct osmo_sockaddr *addr) +{ + RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair; + RANAP_RAB_SetupOrModifyItemFirst_t _rab_setup_or_modify_item_first; + RANAP_RAB_SetupOrModifyItemFirst_t *rab_setup_or_modify_item_first = &_rab_setup_or_modify_item_first; + RANAP_TransportLayerInformation_t *old_transport_layer_information = NULL; + RANAP_TransportLayerInformation_t *new_transport_layer_information = NULL; + struct osmo_sockaddr addr_old; + bool uses_x213_nsap; + int rc; + + protocol_ie_field_pair = prot_ie_field_pair_from_ass_req_ies(ies); + if (!protocol_ie_field_pair) + return -EINVAL; + + if (protocol_ie_field_pair->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem) { + RANAP_DEBUG("Rewriting transport layer information failed, unexpected IE field-pair type!\n"); + return -EINVAL; + } + + /* Decode setup-or-modifiy item (first) */ + rc = ranap_decode_rab_setupormodifyitemfirst(rab_setup_or_modify_item_first, + &protocol_ie_field_pair->firstValue); + if (rc < 0) + return -EINVAL; + + /* Replace transport-layer-information */ + if (rab_setup_or_modify_item_first->transportLayerInformation->iuTransportAssociation.present == + RANAP_IuTransportAssociation_PR_bindingID) { + old_transport_layer_information = rab_setup_or_modify_item_first->transportLayerInformation; + + /* Before we can re-encode the transport layer information, we need to know the format it was + * encoded in. */ + rc = ranap_transp_layer_addr_decode2(&addr_old, &uses_x213_nsap, + &old_transport_layer_information->transportLayerAddress); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + /* Encode a new transport layer information field */ + new_transport_layer_information = ranap_new_transp_info_rtp(addr, uses_x213_nsap); + if (!new_transport_layer_information) { + rc = -EINVAL; + goto error; + } + + rab_setup_or_modify_item_first->transportLayerInformation = new_transport_layer_information; + } else { + RANAP_DEBUG("Rewriting transport layer information failed, no bindingID (port)!\n"); + rc = -EINVAL; + goto error; + } + + /* Reencode transport-layer-information */ + rc = ANY_fromType_aper(&protocol_ie_field_pair->firstValue, &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, + rab_setup_or_modify_item_first); + if (rc < 0) { + RANAP_DEBUG("Rewriting transport layer information failed, could not reencode\n"); + rc = -EINVAL; + goto error; + } + +error: + /* Restore original state of the modified ASN.1 struct so that the asn1c free mechanisms can work properly */ + if (old_transport_layer_information) + rab_setup_or_modify_item_first->transportLayerInformation = old_transport_layer_information; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, rab_setup_or_modify_item_first); + if (new_transport_layer_information) + ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, new_transport_layer_information); + return rc; +} + +/*! Replace IP address and port in RANAP_RAB_AssignmentResponseIEs. + * \ptmap[inout] ies user provided memory with RANAP_RAB_AssignmentResponseIEs. + * \ptmap[in] addr user provided memory that contains the new RTP stream IP-Address and port number. + * \returns 0 on success; negative on error. */ +int ranap_rab_ass_resp_ies_replace_inet_addr(RANAP_RAB_AssignmentResponseIEs_t *ies, struct osmo_sockaddr *addr) +{ + RANAP_IE_t *setup_or_modified_list_ie; + RANAP_RAB_SetupOrModifiedItemIEs_t _rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItemIEs_t *rab_setup_or_modified_items_ies = &_rab_setup_or_modified_items_ies; + RANAP_RAB_SetupOrModifiedItem_t *rab_setup_or_modified_item; + RANAP_TransportLayerInformation_t *temp_transport_layer_information = NULL; + RANAP_TransportLayerAddress_t *old_transport_layer_address = NULL; + RANAP_IuTransportAssociation_t *old_iu_transport_association = NULL; + struct osmo_sockaddr addr_old; + bool uses_x213_nsap; + int rc; + + setup_or_modified_list_ie = setup_or_modif_item_from_rab_ass_resp(ies); + if (!setup_or_modified_list_ie) + return -EINVAL; + + rc = ranap_decode_rab_setupormodifieditemies_fromlist(rab_setup_or_modified_items_ies, + &setup_or_modified_list_ie->value); + if (rc < 0) + return -EINVAL; + + rab_setup_or_modified_item = &rab_setup_or_modified_items_ies->raB_SetupOrModifiedItem; + + /* Before we can re-encode the transport layer address, we need to know the format it was encoded in. */ + rc = ranap_transp_layer_addr_decode2(&addr_old, &uses_x213_nsap, + rab_setup_or_modified_item->transportLayerAddress); + if (rc < 0) { + rc = -EINVAL; + goto error; + } + + /* Generate a temporary transport layer information, from which we can use the transport layer address and + * the iu transport association to update the setup or modified item */ + temp_transport_layer_information = ranap_new_transp_info_rtp(addr, uses_x213_nsap); + if (!temp_transport_layer_information) { + rc = -EINVAL; + goto error; + } + + /* Replace transport layer address and iu transport association */ + old_transport_layer_address = rab_setup_or_modified_item->transportLayerAddress; + old_iu_transport_association = rab_setup_or_modified_item->iuTransportAssociation; + rab_setup_or_modified_item->transportLayerAddress = &temp_transport_layer_information->transportLayerAddress; + rab_setup_or_modified_item->iuTransportAssociation = &temp_transport_layer_information->iuTransportAssociation; + + /* Reencode modified setup or modified list */ + rc = ANY_fromType_aper(&setup_or_modified_list_ie->value, &asn_DEF_RANAP_RAB_SetupOrModifiedItem, + rab_setup_or_modified_items_ies); + if (rc < 0) { + RANAP_DEBUG("Rewriting transport layer address failed, could not reencode\n"); + rc = -EINVAL; + goto error; + } + +error: + /* Restore original state of the modified ASN.1 struct so that the asn1c free mechanisms can work properly */ + if (old_transport_layer_address) + rab_setup_or_modified_item->transportLayerAddress = old_transport_layer_address; + if (old_iu_transport_association) + rab_setup_or_modified_item->iuTransportAssociation = old_iu_transport_association; + if (temp_transport_layer_information) + ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, temp_transport_layer_information); + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedItem, rab_setup_or_modified_items_ies); + + return rc; +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 899e436..f9da51f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = \ + ranap_rab_ass \ $(NULL)
# The `:;' works around a Bash 3.2 bug when the output is not writeable. diff --git a/tests/ranap_rab_ass/Makefile.am b/tests/ranap_rab_ass/Makefile.am new file mode 100644 index 0000000..8d1df7a --- /dev/null +++ b/tests/ranap_rab_ass/Makefile.am @@ -0,0 +1,37 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + -ggdb3 \ + $(LIBASN1C_CFLAGS) \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) \ + $(LIBOSMORANAP_CFLAGS) \ + $(LIBOSMOSIGTRAN_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +EXTRA_DIST = \ + ranap_rab_ass_test.ok \ + $(NULL) + +noinst_PROGRAMS = \ + ranap_rab_ass_test \ + $(NULL) + +ranap_rab_ass_test_SOURCES = \ + ranap_rab_ass_test.c \ + $(NULL) + +ranap_rab_ass_test_LDADD = \ + $(LIBASN1C_LIBS) \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(LIBOSMORANAP_LIBS) \ + $(LIBOSMOSIGTRAN_LIBS) \ + $(COVERAGE_LDFLAGS) \ + $(top_builddir)/src/osmo-hnbgw/ranap_rab_ass.o \ + $(NULL) diff --git a/tests/ranap_rab_ass/ranap_rab_ass_test.c b/tests/ranap_rab_ass/ranap_rab_ass_test.c new file mode 100644 index 0000000..c67b5aa --- /dev/null +++ b/tests/ranap_rab_ass/ranap_rab_ass_test.c @@ -0,0 +1,340 @@ +/* (C) 2021 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * All Rights Reserved + * + * Author: Philipp Maier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +#include <osmocom/core/application.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/hnbgw/hnbgw.h> + +#include <osmocom/ranap/ranap_ies_defs.h> +#include <osmocom/ranap/iu_helpers.h> +#include <osmocom/hnbgw/ranap_rab_ass.h> +#include <osmocom/ranap/ranap_common.h> +#include <osmocom/ranap/ranap_common_cn.h> +#include <osmocom/ranap/ranap_common_ran.h> + +static void *tall_hnb_ctx; +static void *msgb_ctx; +extern void *talloc_asn1_ctx; + +void test_ranap_rab_ass_req_decode_encode(void) +{ + int rc; + ranap_message message; + uint8_t testvec[] = { + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x01, 0x00, + 0x36, 0x40, 0x52, 0x00, 0x00, 0x01, 0x00, 0x35, + 0x00, 0x48, 0x78, 0x22, 0xcd, 0x80, 0x10, 0x2f, + 0xa7, 0x20, 0x1a, 0x2c, 0x00, 0x00, 0xf4, 0x4c, + 0x08, 0x0a, 0x02, 0x80, 0x00, 0x51, 0x40, 0x00, + 0x27, 0x20, 0x28, 0x14, 0x00, 0x67, 0x40, 0x00, + 0x00, 0x22, 0x28, 0x14, 0x00, 0x3c, 0x40, 0x00, + 0x00, 0x00, 0x50, 0x3d, 0x02, 0x00, 0x02, 0x27, + 0xc0, 0x35, 0x00, 0x01, 0x0a, 0x09, 0x01, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x76, + 0x00, 0x00, 0x40, 0x01, 0x00, 0x00 + }; + uint8_t encoded[sizeof(testvec)]; + + rc = ranap_ran_rx_co_decode(talloc_asn1_ctx, &message, testvec, sizeof(testvec)); + OSMO_ASSERT(rc == 0); + + rc = ranap_rab_ass_req_encode(encoded, sizeof(encoded), &message.msg.raB_AssignmentRequestIEs); + printf("ranap_rab_ass_req_encode rc=%d\n", rc); + + printf("INPUT: %s\n", osmo_hexdump_nospc(testvec, sizeof(testvec))); + printf("RESULT: %s\n", osmo_hexdump_nospc(encoded, sizeof(encoded))); + OSMO_ASSERT(memcmp(testvec, encoded, sizeof(testvec)) == 0); + + ranap_ran_rx_co_free(&message); +} + +void test_ranap_rab_ass_resp_decode_encode(void) +{ + int rc; + ranap_message message; + uint8_t testvec[] = { + 0x60, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x00, + 0x34, 0x40, 0x23, 0x00, 0x00, 0x01, 0x00, 0x33, + 0x40, 0x1c, 0x60, 0x3a, 0x7c, 0x35, 0x00, 0x01, + 0x0a, 0x09, 0x01, 0xa4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x04, 0x0a, 0x00, 0x00 + }; + uint8_t encoded[sizeof(testvec)]; + + rc = ranap_cn_rx_co_decode(talloc_asn1_ctx, &message, testvec, sizeof(testvec)); + OSMO_ASSERT(rc == 0); + + rc = ranap_rab_ass_resp_encode(encoded, sizeof(encoded), &message.msg.raB_AssignmentResponseIEs); + printf("ranap_rab_ass_resp_encode rc=%d\n", rc); + + printf("INPUT: %s\n", osmo_hexdump_nospc(testvec, sizeof(testvec))); + printf("RESULT: %s\n", osmo_hexdump_nospc(encoded, sizeof(encoded))); + OSMO_ASSERT(memcmp(testvec, encoded, sizeof(testvec)) == 0); + + ranap_cn_rx_co_free(&message); +} + +void test_ranap_rab_ass_req_extract_inet_addr(void) +{ + int rc; + struct osmo_sockaddr addr; + struct osmo_sockaddr_str addr_str; + uint8_t rab_id; + ranap_message message; + uint8_t testvec[] = { + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x01, 0x00, + 0x36, 0x40, 0x52, 0x00, 0x00, 0x01, 0x00, 0x35, + 0x00, 0x48, 0x78, 0x22, 0xcd, 0x80, 0x10, 0x2f, + 0xa7, 0x20, 0x1a, 0x2c, 0x00, 0x00, 0xf4, 0x4c, + 0x08, 0x0a, 0x02, 0x80, 0x00, 0x51, 0x40, 0x00, + 0x27, 0x20, 0x28, 0x14, 0x00, 0x67, 0x40, 0x00, + 0x00, 0x22, 0x28, 0x14, 0x00, 0x3c, 0x40, 0x00, + 0x00, 0x00, 0x50, 0x3d, 0x02, 0x00, 0x02, 0x27, + 0xc0, 0x35, 0x00, 0x01, 0x0a, 0x09, 0x01, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x76, + 0x00, 0x00, 0x40, 0x01, 0x00, 0x00 + }; + + rc = ranap_ran_rx_co_decode(talloc_asn1_ctx, &message, testvec, sizeof(testvec)); + OSMO_ASSERT(rc == 0); + rc = ranap_rab_ass_req_ies_extract_inet_addr(&addr, &rab_id, &message.msg.raB_AssignmentRequestIEs); + osmo_sockaddr_str_from_sockaddr(&addr_str, &addr.u.sas); + printf("ranap_rab_ass_req_extract_inet_addr rc=%d\n", rc); + printf("RESULT: addr=%s, port=%u, rab-id=%02x\n", addr_str.ip, addr_str.port, rab_id); + ranap_ran_rx_co_free(&message); +} + +void test_ranap_rab_ass_resp_extract_inet_addr(void) +{ + int rc; + struct osmo_sockaddr addr; + struct osmo_sockaddr_str addr_str; + ranap_message message; + uint8_t testvec[] = { + 0x60, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x00, + 0x34, 0x40, 0x23, 0x00, 0x00, 0x01, 0x00, 0x33, + 0x40, 0x1c, 0x60, 0x3a, 0x7c, 0x35, 0x00, 0x01, + 0x0a, 0x09, 0x01, 0xa4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x04, 0x0a, 0x00, 0x00 + }; + + rc = ranap_cn_rx_co_decode(talloc_asn1_ctx, &message, testvec, sizeof(testvec)); + OSMO_ASSERT(rc == 0); + rc = ranap_rab_ass_resp_ies_extract_inet_addr(&addr, &message.msg.raB_AssignmentResponseIEs); + osmo_sockaddr_str_from_sockaddr(&addr_str, &addr.u.sas); + printf("ranap_rab_ass_resp_extract_inet_addr rc=%d\n", rc); + printf("RESULT: addr=%s, port=%u\n", addr_str.ip, addr_str.port); + ranap_cn_rx_co_free(&message); +} + +void test_ranap_rab_ass_req_replace_inet_addr(void) +{ + int rc; + struct osmo_sockaddr addr; + struct osmo_sockaddr_str addr_str; + ranap_message message; + uint8_t testvec_in[] = { + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x01, 0x00, + 0x36, 0x40, 0x52, 0x00, 0x00, 0x01, 0x00, 0x35, + 0x00, 0x48, 0x78, 0x4e, 0xcd, 0x80, 0x10, 0x2f, + 0xa7, 0x20, 0x1a, 0x2c, 0x00, 0x00, 0xf4, 0x4c, + 0x08, 0x0a, 0x02, 0x80, 0x00, 0x51, 0x40, 0x00, + 0x27, 0x20, 0x28, 0x14, 0x00, 0x67, 0x40, 0x00, + 0x00, 0x22, 0x28, 0x14, 0x00, 0x3c, 0x40, 0x00, + 0x00, 0x00, 0x50, 0x3d, 0x02, 0x00, 0x02, 0x27, + 0xc0, 0x35, 0x00, 0x01, 0x0a, 0x09, 0x01, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0xba, + 0x00, 0x00, 0x40, 0x01, 0x00 + }; + uint8_t testvec_expected_out[] = { + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x01, 0x00, + 0x36, 0x40, 0x52, 0x00, 0x00, 0x01, 0x00, 0x35, + 0x00, 0x48, 0x78, 0x4e, 0xcd, 0x80, 0x10, 0x2f, + 0xa7, 0x20, 0x1a, 0x2c, 0x00, 0x00, 0xf4, 0x4c, + 0x08, 0x0a, 0x02, 0x80, 0x00, 0x51, 0x40, 0x00, + 0x27, 0x20, 0x28, 0x14, 0x00, 0x67, 0x40, 0x00, + 0x00, 0x22, 0x28, 0x14, 0x00, 0x3c, 0x40, 0x00, + 0x00, 0x00, 0x50, 0x3d, 0x02, 0x00, 0x02, 0x27, + 0xc0, 0x35, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0xd2, + 0x00, 0x00, 0x40, 0x01, 0x00 + }; + + rc = ranap_ran_rx_co_decode(talloc_asn1_ctx, &message, testvec_in, sizeof(testvec_in)); + OSMO_ASSERT(rc == 0); + + rc = ranap_rab_ass_req_ies_extract_inet_addr(&addr, NULL, &message.msg.raB_AssignmentRequestIEs); + OSMO_ASSERT(rc == 0); + osmo_sockaddr_str_from_sockaddr(&addr_str, &addr.u.sas); + printf("before: addr=%s, port=%u\n", addr_str.ip, addr_str.port); + + memset(&addr_str, 0, sizeof(addr_str)); + addr_str.af = AF_INET; + addr_str.port = 1234; + osmo_strlcpy(addr_str.ip, "1.2.3.4", sizeof(addr_str.ip)); + osmo_sockaddr_str_to_sockaddr(&addr_str, &addr.u.sas); + + rc = ranap_rab_ass_req_ies_replace_inet_addr(&message.msg.raB_AssignmentRequestIEs, &addr); + printf("ranap_rab_ass_req_replace_inet_addr rc=%d\n", rc); + + rc = ranap_rab_ass_req_ies_extract_inet_addr(&addr, NULL, &message.msg.raB_AssignmentRequestIEs); + OSMO_ASSERT(rc == 0); + osmo_sockaddr_str_from_sockaddr(&addr_str, &addr.u.sas); + printf("after: addr=%s, port=%u\n", addr_str.ip, addr_str.port); + + rc = ranap_rab_ass_req_encode(testvec_in, sizeof(testvec_in), &message.msg.raB_AssignmentRequestIEs); + OSMO_ASSERT(rc == sizeof(testvec_in)); + OSMO_ASSERT(memcmp(testvec_in, testvec_expected_out, sizeof(testvec_in)) == 0); + + ranap_ran_rx_co_free(&message); +} + +void test_ranap_rab_ass_resp_replace_inet_addr(void) +{ + int rc; + struct osmo_sockaddr addr; + struct osmo_sockaddr_str addr_str; + ranap_message message; + uint8_t testvec_in[] = { + 0x60, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x00, + 0x34, 0x40, 0x23, 0x00, 0x00, 0x01, 0x00, 0x33, + 0x40, 0x1c, 0x60, 0x32, 0x7c, 0x35, 0x00, 0x01, + 0x0a, 0x09, 0x01, 0xa4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x04, 0x0a, 0x00, 0x00 + }; + uint8_t testvec_expected_out[] = { + 0x60, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x00, + 0x34, 0x40, 0x23, 0x00, 0x00, 0x01, 0x00, 0x33, + 0x40, 0x1c, 0x60, 0x32, 0x7c, 0x35, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x04, 0xd2, 0x00, 0x00 + }; + + rc = ranap_cn_rx_co_decode(talloc_asn1_ctx, &message, testvec_in, sizeof(testvec_in)); + OSMO_ASSERT(rc == 0); + + rc = ranap_rab_ass_resp_ies_extract_inet_addr(&addr, &message.msg.raB_AssignmentResponseIEs); + OSMO_ASSERT(rc == 0); + osmo_sockaddr_str_from_sockaddr(&addr_str, &addr.u.sas); + printf("before: addr=%s, port=%u\n", addr_str.ip, addr_str.port); + + memset(&addr_str, 0, sizeof(addr_str)); + addr_str.af = AF_INET; + addr_str.port = 1234; + osmo_strlcpy(addr_str.ip, "1.2.3.4", sizeof(addr_str.ip)); + osmo_sockaddr_str_to_sockaddr(&addr_str, &addr.u.sas); + + rc = ranap_rab_ass_resp_ies_replace_inet_addr(&message.msg.raB_AssignmentResponseIEs, &addr); + printf("ranap_rab_ass_resp_replace_inet_addr rc=%d\n", rc); + + rc = ranap_rab_ass_resp_ies_extract_inet_addr(&addr, &message.msg.raB_AssignmentResponseIEs); + OSMO_ASSERT(rc == 0); + osmo_sockaddr_str_from_sockaddr(&addr_str, &addr.u.sas); + printf("after: addr=%s, port=%u\n", addr_str.ip, addr_str.port); + + rc = ranap_rab_ass_resp_encode(testvec_in, sizeof(testvec_in), &message.msg.raB_AssignmentResponseIEs); + OSMO_ASSERT(rc == sizeof(testvec_in)); + OSMO_ASSERT(memcmp(testvec_in, testvec_expected_out, sizeof(testvec_in)) == 0); + + ranap_cn_rx_co_free(&message); +} + +static const struct log_info_cat log_cat[] = { + [DRANAP] = { + .name = "RANAP", .loglevel = LOGL_DEBUG, .enabled = 1, + .color = "", + .description = "RAN Application Part", + }, +}; + +static const struct log_info test_log_info = { + .cat = log_cat, + .num_cat = ARRAY_SIZE(log_cat), +}; + +int test_init(void) +{ + int rc; + + tall_hnb_ctx = talloc_named_const(NULL, 0, "hnb_context"); + msgb_ctx = msgb_talloc_ctx_init(NULL, 0); + talloc_asn1_ctx = talloc_named_const(NULL, 0, "asn1_context"); + + rc = osmo_init_logging2(tall_hnb_ctx, &test_log_info); + if (rc < 0) + exit(1); + + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 0); + log_set_print_category_hex(osmo_stderr_target, 0); + return rc; +} + +void test_cleanup(void) +{ + if (talloc_total_blocks(msgb_ctx) != 1 || talloc_total_size(msgb_ctx) != 0) + talloc_report_full(msgb_ctx, stderr); + + OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1); + OSMO_ASSERT(talloc_total_size(msgb_ctx) == 0); + talloc_free(msgb_ctx); + + if (talloc_total_blocks(talloc_asn1_ctx) != 1 || talloc_total_size(talloc_asn1_ctx) != 0) + talloc_report_full(talloc_asn1_ctx, stderr); + + OSMO_ASSERT(talloc_total_blocks(talloc_asn1_ctx) == 1); + OSMO_ASSERT(talloc_total_size(talloc_asn1_ctx) == 0); + talloc_free(talloc_asn1_ctx); +} + +int main(int argc, char **argv) +{ + test_init(); + + test_ranap_rab_ass_req_decode_encode(); + test_ranap_rab_ass_resp_decode_encode(); + + test_ranap_rab_ass_req_extract_inet_addr(); + test_ranap_rab_ass_resp_extract_inet_addr(); + test_ranap_rab_ass_req_replace_inet_addr(); + test_ranap_rab_ass_resp_replace_inet_addr(); + + test_cleanup(); + return 0; +} + +/* Stub */ +const char *hnb_context_name(struct hnb_context *ctx) +{ + return "TEST"; +} diff --git a/tests/ranap_rab_ass/ranap_rab_ass_test.ok b/tests/ranap_rab_ass/ranap_rab_ass_test.ok new file mode 100644 index 0000000..f7b4b67 --- /dev/null +++ b/tests/ranap_rab_ass/ranap_rab_ass_test.ok @@ -0,0 +1,16 @@ +ranap_rab_ass_req_encode rc=93 +INPUT: 0000005900000100364052000001003500487822cd80102fa7201a2c0000f44c080a028000514000272028140067400000222814003c40000000503d02000227c03500010a0901a200000000000000000000000000401f76000040010000 +RESULT: 0000005900000100364052000001003500487822cd80102fa7201a2c0000f44c080a028000514000272028140067400000222814003c40000000503d02000227c03500010a0901a200000000000000000000000000401f76000040010000 +ranap_rab_ass_resp_encode rc=46 +INPUT: 6000002a000001003440230000010033401c603a7c3500010a0901a40000000000000000000000000040040a0000 +RESULT: 6000002a000001003440230000010033401c603a7c3500010a0901a40000000000000000000000000040040a0000 +ranap_rab_ass_req_extract_inet_addr rc=0 +RESULT: addr=10.9.1.162, port=8054, rab-id=11 +ranap_rab_ass_resp_extract_inet_addr rc=0 +RESULT: addr=10.9.1.164, port=1034 +before: addr=10.9.1.162, port=8122 +ranap_rab_ass_req_replace_inet_addr rc=0 +after: addr=1.2.3.4, port=1234 +before: addr=10.9.1.164, port=1034 +ranap_rab_ass_resp_replace_inet_addr rc=0 +after: addr=1.2.3.4, port=1234 diff --git a/tests/testsuite.at b/tests/testsuite.at index 65d1ca0..84d85cf 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,8 +1,8 @@ AT_INIT AT_BANNER([Regression tests.])
-#AT_SETUP([foobar]) -#AT_KEYWORDS([foobar]) -#cat $abs_srcdir/foobar/foobar_test.ok > expout -#AT_CHECK([$abs_top_builddir/tests/foobar/foobar_test], [], [expout], [ignore]) -#AT_CLEANUP +AT_SETUP([ranap_rab_ass]) +AT_KEYWORDS([ranap_rab_ass]) +cat $abs_srcdir/ranap_rab_ass/ranap_rab_ass_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/ranap_rab_ass/ranap_rab_ass_test], [0], [expout], [ignore]) +AT_CLEANUP \ No newline at end of file