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(a)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(a)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
--
To view, visit
https://gerrit.osmocom.org/c/osmo-hnbgw/+/26792
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-hnbgw
Gerrit-Branch: master
Gerrit-Change-Id: I58b542bf23ff5e1db2ccf6833fec91d9ba332837
Gerrit-Change-Number: 26792
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: newchange