diff --git a/include/osmocom/ranap/Makefile.am b/include/osmocom/ranap/Makefile.am index 1606928c..26624841 100644 --- a/include/osmocom/ranap/Makefile.am +++ b/include/osmocom/ranap/Makefile.am @@ -10,6 +10,7 @@ ranap_HEADERS = \ 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 0343a57b..7511a752 100644 --- a/include/osmocom/ranap/ranap_common.h +++ b/include/osmocom/ranap/ranap_common.h @@ -596,6 +596,9 @@ struct gprs_ra_id; extern int _ranap_DRANAP; #define RANAP_DEBUG(x, args ...) DEBUGP(_ranap_DRANAP, x, ## args) +/* Callback to be used with decoder functions in ranap_common_cn.c ranap_common_ran.c */ +typedef void (*ranap_handle_cb)(void *ctx, ranap_message *ranap_msg); + extern int asn1_xer_print; extern const struct value_string ranap_presence_vals[5]; diff --git a/include/osmocom/ranap/ranap_common_cn.h b/include/osmocom/ranap/ranap_common_cn.h index 90ff6daf..fb65049f 100644 --- a/include/osmocom/ranap/ranap_common_cn.h +++ b/include/osmocom/ranap/ranap_common_cn.h @@ -5,8 +5,6 @@ #include #include -typedef void (*ranap_handle_cb)(void *ctx, ranap_message *ranap_msg); - /* free a decoded connection-less RANAP message */ void ranap_cn_rx_cl_free(ranap_message *message); diff --git a/include/osmocom/ranap/ranap_common_ran.h b/include/osmocom/ranap/ranap_common_ran.h new file mode 100644 index 00000000..5eef2724 --- /dev/null +++ b/include/osmocom/ranap/ranap_common_ran.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include +#include + +/* free a decoded connection-oriented RANAP message */ +void ranap_ran_rx_co_free(ranap_message *message); + +/* decode a connection-oriented RANAP message */ +int ranap_ran_rx_co_decode(void *ctx, ranap_message *message, uint8_t *data, size_t len); + +/* 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 6c10564e..0407fa30 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,7 +75,7 @@ libosmo_ranap_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(RANAP_LIBVERSION) 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 00000000..f3fa519c --- /dev/null +++ b/src/ranap_common_ran.c @@ -0,0 +1,184 @@ +/* RANAP interface for a ran-network node */ + +/* (C) 2021 by sysmocom s.f.m.c. GmbH + * 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 . + * + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#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 CN, 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 CN\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 CN, ignoring\n", + get_value_string(ranap_procedure_code_vals, pdu->choice.successfulOutcome.procedureCode)); + rc = -1; + break; + case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: + LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " + "unsuccessful outcome procedure %s (CO) from CN, 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 CN, ignoring\n", + get_value_string(ranap_procedure_code_vals, pdu->choice.outcome.procedureCode)); + rc = -1; + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " + "presence %s (CO) from CN, ignoring\n", get_value_string(ranap_presence_vals, pdu->present)); + rc = -1; + break; + } + + return rc; +} + +/* free a decoded connection-oriented RANAP message */ +void ranap_ran_rx_co_free(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 " + "successful outcome procedure (CO) from CN\n"); + break; + case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing unsupported RANAP " + "unsuccessful outcome procedure (CO) from CN\n"); + break; + case RANAP_RANAP_PDU_PR_outcome: + LOGP(DRANAP, LOGL_NOTICE, "Not freeing unsupported RANAP " + "outcome procedure (CO) from CN\n"); + break; + default: + LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " + "presence %s (CO) from CN, ignoring\n", + get_value_string(ranap_presence_vals, message->direction)); + break; + } +} + +/* decode a connection-oriented RANAP message */ +int ranap_ran_rx_co_decode(void *ctx, ranap_message *message, uint8_t *data, size_t len) +{ + RANAP_RANAP_PDU_t *pdu = NULL; + 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); + + ASN_STRUCT_FREE(asn_DEF_RANAP_RANAP_PDU, pdu); + + return rc; +} + +/* 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_message message; + int rc; + + rc = ranap_ran_rx_co_decode(ctx, &message, data, len); + + 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 */ + ranap_ran_rx_co_free(&message); + + return rc; +}