dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-iuh/+/26955 )
Change subject: ranap_common_ran: add decoder for RAN/RNC originated messages ......................................................................
ranap_common_ran: add decoder for RAN/RNC originated messages
Lets add a counterpart for ranap_common_cn that works the same, but decodes RAN/RNC originated messages.
Related: OS#515 Change-Id: Iad4c2743d4d1ddf8ad49002d1fe6866f22eb9e98 --- M include/osmocom/ranap/Makefile.am M include/osmocom/ranap/ranap_common.h M include/osmocom/ranap/ranap_common_cn.h A include/osmocom/ranap/ranap_common_ran.h M src/Makefile.am A src/ranap_common_ran.c 6 files changed, 280 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-iuh refs/changes/55/26955/1
diff --git a/include/osmocom/ranap/Makefile.am b/include/osmocom/ranap/Makefile.am index 1606928..2662484 100644 --- a/include/osmocom/ranap/Makefile.am +++ b/include/osmocom/ranap/Makefile.am @@ -10,6 +10,7 @@ ranap_ies_defs.h \ ranap_common.h \ ranap_common_cn.h \ + ranap_common_ran.h \ ranap_msg_factory.h \ iu_helpers.h \ iu_client.h \ diff --git a/include/osmocom/ranap/ranap_common.h b/include/osmocom/ranap/ranap_common.h index e9e7a2e..efffd25 100644 --- a/include/osmocom/ranap/ranap_common.h +++ b/include/osmocom/ranap/ranap_common.h @@ -651,3 +651,5 @@
int ranap_decode_procedure_code(const uint8_t *ranap_pdu_encoded, unsigned int len); + +typedef void (*ranap_handle_cb)(void *ctx, ranap_message *ranap_msg); diff --git a/include/osmocom/ranap/ranap_common_cn.h b/include/osmocom/ranap/ranap_common_cn.h index dfce358..7964b7c 100644 --- a/include/osmocom/ranap/ranap_common_cn.h +++ b/include/osmocom/ranap/ranap_common_cn.h @@ -5,8 +5,6 @@ #include <osmocom/ranap/ranap_common.h> #include <osmocom/ranap/ranap_ies_defs.h>
-typedef void (*ranap_handle_cb)(void *ctx, ranap_message *ranap_msg); - /* receive a connection-less RANAP message */ int ranap_cn_rx_cl(ranap_handle_cb cb, void *ctx, uint8_t *data, size_t len);
diff --git a/include/osmocom/ranap/ranap_common_ran.h b/include/osmocom/ranap/ranap_common_ran.h new file mode 100644 index 0000000..431a276 --- /dev/null +++ b/include/osmocom/ranap/ranap_common_ran.h @@ -0,0 +1,9 @@ +#pragma once + +#include <stdint.h> + +#include <osmocom/ranap/ranap_common.h> +#include <osmocom/ranap/ranap_ies_defs.h> + +/* receive a connection-oriented RANAP message */ +int ranap_ran_rx_co(ranap_handle_cb cb, void *ctx, uint8_t *data, size_t len); diff --git a/src/Makefile.am b/src/Makefile.am index 6c10564..0407fa3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,7 +75,7 @@ libosmo_ranap_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOVTY_LIBS) $(OSMOSIGTRAN_LIBS) \ $(ASN1C_LIBS) ranap/libosmo-asn1-ranap.la libosmo_ranap_la_SOURCES = ranap_common.c ranap_encoder.c ranap_decoder.c ranap_msg_factory.c iu_helpers.c \ - ranap_common_cn.c iu_client.c iu_client_vty.c + ranap_common_cn.c ranap_common_ran.c iu_client.c iu_client_vty.c
libosmo_rua_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HNBAP_LIBVERSION) libosmo_rua_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOVTY_LIBS) $(OSMOSIGTRAN_LIBS) \ diff --git a/src/ranap_common_ran.c b/src/ranap_common_ran.c new file mode 100644 index 0000000..1a0b222 --- /dev/null +++ b/src/ranap_common_ran.c @@ -0,0 +1,267 @@ +/* RANAP interface for a ran-network node */ + +/* (C) 2015 by Harald Welte laforge@gnumonks.org + * 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 <errno.h> +#include <string.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/logging.h> + +#include <osmocom/ranap/ranap_common.h> +#include <osmocom/ranap/ranap_common_ran.h> +#include <osmocom/ranap/ranap_ies_defs.h> + +#define DRANAP _ranap_DRANAP + +static int ran_ranap_rx_initiating_msg_co(void *ctx, RANAP_InitiatingMessage_t * imsg, ranap_message * message) +{ + int rc = 0; + + message->procedureCode = imsg->procedureCode; + message->criticality = imsg->criticality; + + DEBUGP(DRANAP, "Rx CO IM (%s)\n", get_value_string(ranap_procedure_code_vals, imsg->procedureCode)); + + switch (imsg->procedureCode) { + case RANAP_ProcedureCode_id_RAB_Assignment: + rc = ranap_decode_rab_assignmentrequesties(&message->msg.raB_AssignmentRequestIEs, &imsg->value); + break; + case RANAP_ProcedureCode_id_Iu_Release: + rc = ranap_decode_iu_releasecommandies(&message->msg.iu_ReleaseCommandIEs, &imsg->value); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP Procedure %s (CO, IM) from RNC, ignoring\n", + get_value_string(ranap_procedure_code_vals, imsg->procedureCode)); + rc = -1; + break; + } + + return rc; +} + +static void ran_ranap_free_initiating_msg_co(ranap_message * message) +{ + switch (message->procedureCode) { + case RANAP_ProcedureCode_id_RAB_Assignment: + ranap_free_rab_assignmentrequesties(&message->msg.raB_AssignmentRequestIEs); + break; + case RANAP_ProcedureCode_id_Iu_Release: + ranap_free_iu_releasecommandies(&message->msg.iu_ReleaseCommandIEs); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing suspicious RANAP " + "Procedure %s (CO, IM) from RNC\n", + get_value_string(ranap_procedure_code_vals, message->procedureCode)); + break; + } +} + +static int cn_ranap_rx_successful_msg_co(void *ctx, RANAP_SuccessfulOutcome_t * imsg, ranap_message * message) +{ + int rc = 0; + + message->procedureCode = imsg->procedureCode; + message->criticality = imsg->criticality; + + DEBUGP(DRANAP, "Rx CO SO (%s)\n", get_value_string(ranap_procedure_code_vals, imsg->procedureCode)); + + switch (imsg->procedureCode) { + case RANAP_ProcedureCode_id_RAB_Assignment: + /* RAB assignment response */ + rc = ranap_decode_rab_assignmentresponseies(&message->msg.raB_AssignmentResponseIEs, &imsg->value); + break; + case RANAP_ProcedureCode_id_SecurityModeControl: + /* Security Mode Complete */ + rc = ranap_decode_securitymodecompleteies(&message->msg.securityModeCompleteIEs, &imsg->value); + break; + case RANAP_ProcedureCode_id_Iu_Release: + /* Iu release Complete; confirmation of CN-initiated release */ + rc = ranap_decode_iu_releasecompleteies(&message->msg.iu_ReleaseCompleteIEs, &imsg->value); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " + "Procedure %s (SO) from RNC, ignoring\n", + get_value_string(ranap_procedure_code_vals, imsg->procedureCode)); + rc = -1; + break; + } + + return rc; +} + +static void cn_ranap_free_successful_msg_co(ranap_message * message) +{ + switch (message->procedureCode) { + case RANAP_ProcedureCode_id_RAB_Assignment: + /* RAB assignment response */ + ranap_free_rab_assignmentresponseies(&message->msg.raB_AssignmentResponseIEs); + break; + case RANAP_ProcedureCode_id_SecurityModeControl: + /* Security Mode Complete */ + ranap_free_securitymodecompleteies(&message->msg.securityModeCompleteIEs); + break; + case RANAP_ProcedureCode_id_Iu_Release: + /* Iu release Complete; confirmation of CN-initiated release */ + ranap_free_iu_releasecompleteies(&message->msg.iu_ReleaseCompleteIEs); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing suspicious RANAP " + "Procedure %s (SO) from RNC\n", + get_value_string(ranap_procedure_code_vals, message->procedureCode)); + break; + } +} + +static int cn_ranap_rx_outcome_msg_co(void *ctx, RANAP_Outcome_t * imsg, ranap_message * message) +{ + int rc = 0; + + message->procedureCode = imsg->procedureCode; + message->criticality = imsg->criticality; + + DEBUGP(DRANAP, "Rx CO O (%s)\n", get_value_string(ranap_procedure_code_vals, imsg->procedureCode)); + + switch (imsg->procedureCode) { + case RANAP_ProcedureCode_id_RAB_Assignment: + /* RAB assignment response */ + rc = ranap_decode_rab_assignmentresponseies(&message->msg.raB_AssignmentResponseIEs, &imsg->value); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " + "Procedure %s (O) from RNC, ignoring\n", + get_value_string(ranap_procedure_code_vals, imsg->procedureCode)); + rc = -1; + break; + } + + return rc; +} + +static void cn_ranap_free_outcome_msg_co(ranap_message * message) +{ + switch (message->procedureCode) { + case RANAP_ProcedureCode_id_RAB_Assignment: + /* RAB assignment response */ + ranap_free_rab_assignmentresponseies(&message->msg.raB_AssignmentResponseIEs); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing suspicious RANAP " + "Procedure %s (O) from RNC\n", + get_value_string(ranap_procedure_code_vals, message->procedureCode)); + break; + } +} + +static int _ran_ranap_rx_co(void *ctx, RANAP_RANAP_PDU_t * pdu, ranap_message * message) +{ + int rc = 0; + + switch (pdu->present) { + case RANAP_RANAP_PDU_PR_initiatingMessage: + rc = ran_ranap_rx_initiating_msg_co(ctx, &pdu->choice.initiatingMessage, message); + break; + case RANAP_RANAP_PDU_PR_successfulOutcome: + LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " + "successful outcome procedure %s (CO) from RNC, ignoring\n", + get_value_string(ranap_procedure_code_vals, pdu->choice.unsuccessfulOutcome.procedureCode)); + rc = -1; + break; + case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: + LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " + "unsuccessful outcome procedure %s (CO) from RNC, ignoring\n", + get_value_string(ranap_procedure_code_vals, pdu->choice.unsuccessfulOutcome.procedureCode)); + rc = -1; + break; + case RANAP_RANAP_PDU_PR_outcome: + LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " + "outcome procedure %s (CO) from RNC, ignoring\n", + get_value_string(ranap_procedure_code_vals, pdu->choice.unsuccessfulOutcome.procedureCode)); + rc = -1; + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " + "presence %s (CO) from RNC, ignoring\n", get_value_string(ranap_presence_vals, pdu->present)); + rc = -1; + break; + } + + return rc; +} + +static void _ran_ranap_free_co(ranap_message * message) +{ + switch (message->direction) { + case RANAP_RANAP_PDU_PR_initiatingMessage: + ran_ranap_free_initiating_msg_co(message); + break; + case RANAP_RANAP_PDU_PR_successfulOutcome: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing unsupported RANAP " + "unsuccessful outcome procedure (CO) from RNC\n"); + break; + case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing unsupported RANAP " + "unsuccessful outcome procedure (CO) from RNC\n"); + break; + case RANAP_RANAP_PDU_PR_outcome: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing unsupported RANAP " + "unsuccessful outcome procedure (CO) from RNC\n"); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " + "presence %s (CO) from RNC, ignoring\n", + get_value_string(ranap_presence_vals, message->direction)); + break; + } +} + +/* receive a connection-oriented RANAP message and call + * cn_ranap_handle_co() with the resulting ranap_message struct */ +int ranap_ran_rx_co(ranap_handle_cb cb, void *ctx, uint8_t *data, size_t len) +{ + RANAP_RANAP_PDU_t *pdu = NULL; + ranap_message message; + asn_dec_rval_t dec_ret; + int rc; + + memset(&message, 0, sizeof(message)); + + dec_ret = aper_decode(NULL, &asn_DEF_RANAP_RANAP_PDU, (void **)&pdu, data, len, 0, 0); + if (dec_ret.code != RC_OK) { + LOGP(DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n"); + return -1; + } + + message.direction = pdu->present; + + rc = _ran_ranap_rx_co(ctx, pdu, &message); + + if (rc == 0) + (*cb) (ctx, &message); + else + LOGP(DRANAP, LOGL_ERROR, "Not calling ran_ranap_handle_co() due to rc=%d\n", rc); + + /* Free the asn1 structs in message */ + _ran_ranap_free_co(&message); + + ASN_STRUCT_FREE(asn_DEF_RANAP_RANAP_PDU, pdu); + + return rc; +}