From 350814a5cb1abaf3b4c00efd14fbd4a28a5149db Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 10 Sep 2015 22:32:15 +0200 Subject: [PATCH] first dispatch of RUA into RANAP This is becoming more and more of a hack, as asn1c + asn1tostruct.py don't really deal well with the RANAP syntax :( --- src/Makefile | 4 +- src/hnbgw.c | 4 + src/hnbgw_ranap.c | 256 +++++++++++++++++++++++++++++++++++++++++++++ src/hnbgw_ranap.h | 6 ++ src/hnbgw_rua.c | 46 ++++---- src/ranap_common.c | 5 +- src/ranap_common.h | 4 +- 7 files changed, 302 insertions(+), 23 deletions(-) create mode 100644 src/hnbgw_ranap.c create mode 100644 src/hnbgw_ranap.h diff --git a/src/Makefile b/src/Makefile index 17a19d54..97239b54 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,7 +11,7 @@ LDFLAGS:=$(PKG_LDFLAGS) -lsctp HNBAP_OBJS=hnbap_encoder.o hnbap_decoder.o hnbap_common.o RUA_OBJS=rua_encoder.o rua_decoder.o rua_common.o -RANAP_OBJS=#ranap_encoder.o ranap_decoder.o +RANAP_OBJS=ranap_common.o #ranap_encoder.o ranap_decoder.o LIBS=hnbap/libosmo-asn1-hnbap.a rua/libosmo-asn1-rua.a ranap/libosmo-asn1-ranap.a @@ -38,7 +38,7 @@ rua/libosmo-asn1-rua.a: ranap/libosmo-asn1-ranap.a: $(MAKE) -C ranap -hnbgw: asn1helpers.o hnbgw.o hnbgw_hnbap.o hnbgw_rua.o $(HNBAP_OBJS) $(RUA_OBJS) $(RANAP_OBJS) $(LIBS) +hnbgw: asn1helpers.o hnbgw.o hnbgw_hnbap.o hnbgw_rua.o hnbgw_ranap.o $(HNBAP_OBJS) $(RUA_OBJS) $(RANAP_OBJS) $(LIBS) $(CC) $(LDFLAGS) -o $@ $^ %.o: %.c diff --git a/src/hnbgw.c b/src/hnbgw.c index 7c121554..2c49c4dd 100644 --- a/src/hnbgw.c +++ b/src/hnbgw.c @@ -45,6 +45,10 @@ static int hnb_read_cb(struct osmo_fd *fd) if (!msg) return -ENOMEM; + /* we store a reference to the HomeNodeB in the msg->dest for the + * benefit of varoius downstream processing functions */ + msg->dst = hnb; + rc = sctp_recvmsg(fd->fd, msgb_data(msg), msgb_tailroom(msg), NULL, NULL, &sinfo, &flags); if (rc < 0) { diff --git a/src/hnbgw_ranap.c b/src/hnbgw_ranap.c new file mode 100644 index 00000000..44a920b9 --- /dev/null +++ b/src/hnbgw_ranap.c @@ -0,0 +1,256 @@ +#include +#include + +#include +#include +#include + +#include "asn1helpers.h" + +#include "hnbgw.h" +//#include "ranap_common.h" + +#include "ranap/RANAP_RANAP-PDU.h" +#include "ranap/RANAP_ResetAcknowledge.h" +#include "ranap/RANAP_Reset.h" +#include "ranap/RANAP_ProtocolIE-ID.h" +#include "ranap/RANAP_Cause.h" +#include "ranap/RANAP_CN-DomainIndicator.h" +#include "ranap/RANAP_GlobalRNC-ID.h" +#include "ranap/RANAP_CriticalityDiagnostics.h" + + +/*********************************************************************** + * BEGIN auto-generated copy+pasted + ***********************************************************************/ + +/* this is copy+pasted from the asn1tostruct generated code that doesn't + * compile as a whole */ + +#define RANAP_DEBUG(x, args ...) DEBUGP(0, x, ## args) + +extern int asn1_xer_print; + +struct msgb *ranap_generate_successful_outcome( + e_RANAP_ProcedureCode procedureCode, + RANAP_Criticality_t criticality, + asn_TYPE_descriptor_t * td, + void *sptr); + +RANAP_IE_t *ranap_new_ie(RANAP_ProtocolIE_ID_t id, RANAP_Criticality_t criticality, + asn_TYPE_descriptor_t *type, void *sptr); + +#define RESETIES_RANAP_GLOBALRNC_ID_PRESENT (1 << 0) + +typedef struct RANAP_ResetIEs_s { + uint16_t presenceMask; + RANAP_Cause_t cause; + RANAP_CN_DomainIndicator_t cN_DomainIndicator; + RANAP_GlobalRNC_ID_t globalRNC_ID; ///< Optional field +} RANAP_ResetIEs_t; + +#define RESETACKNOWLEDGEIES_RANAP_CRITICALITYDIAGNOSTICS_PRESENT (1 << 0) +#define RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT (1 << 1) + +typedef struct RANAP_ResetAcknowledgeIEs_s { + uint16_t presenceMask; + RANAP_CN_DomainIndicator_t cN_DomainIndicator; + RANAP_CriticalityDiagnostics_t criticalityDiagnostics; ///< Optional field + RANAP_GlobalRNC_ID_t globalRNC_ID; ///< Optional field +} RANAP_ResetAcknowledgeIEs_t; + +int ranap_decode_reseties( + RANAP_ResetIEs_t *resetIEs, + ANY_t *any_p) { + + RANAP_Reset_t reset; + RANAP_Reset_t *reset_p = &reset; + int i, decoded = 0; + int tempDecoded = 0; + assert(any_p != NULL); + assert(resetIEs != NULL); + + RANAP_DEBUG("Decoding message RANAP_ResetIEs (%s:%d)\n", __FILE__, __LINE__); + + ANY_to_type_aper(any_p, &asn_DEF_RANAP_Reset, (void**)&reset_p); + + for (i = 0; i < reset_p->reset_ies.list.count; i++) { + RANAP_IE_t *ie_p; + ie_p = reset_p->reset_ies.list.array[i]; + switch(ie_p->id) { + case RANAP_ProtocolIE_ID_id_Cause: + { + RANAP_Cause_t ranaP_Cause; + RANAP_Cause_t *ranaP_Cause_p = &ranaP_Cause; + tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_Cause, (void**)&ranaP_Cause_p); + if (tempDecoded < 0) { + RANAP_DEBUG("Decoding of IE cause failed\n"); + return -1; + } + decoded += tempDecoded; + if (asn1_xer_print) + xer_fprint(stdout, &asn_DEF_RANAP_Cause, ranaP_Cause_p); + memcpy(&resetIEs->cause, ranaP_Cause_p, sizeof(RANAP_Cause_t)); + } break; + case RANAP_ProtocolIE_ID_id_CN_DomainIndicator: + { + RANAP_CN_DomainIndicator_t ranaP_CNDomainIndicator; + RANAP_CN_DomainIndicator_t *ranaP_CNDomainIndicator_p = &ranaP_CNDomainIndicator; + tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_CN_DomainIndicator, (void**)&ranaP_CNDomainIndicator_p); + if (tempDecoded < 0) { + RANAP_DEBUG("Decoding of IE cN_DomainIndicator failed\n"); + return -1; + } + decoded += tempDecoded; + if (asn1_xer_print) + xer_fprint(stdout, &asn_DEF_RANAP_CN_DomainIndicator, ranaP_CNDomainIndicator_p); + memcpy(&resetIEs->cN_DomainIndicator, ranaP_CNDomainIndicator_p, sizeof(RANAP_CN_DomainIndicator_t)); + } break; + /* Optional field */ + case RANAP_ProtocolIE_ID_id_GlobalRNC_ID: + { +#if 0 + RANAP_GlobalRNC_ID_t ranaP_GlobalRNCID; + RANAP_GlobalRNC_ID_t *ranaP_GlobalRNCID_p = &ranaP_GlobalRNCID; + resetIEs->presenceMask |= RESETIES_RANAP_GLOBALRNC_ID_PRESENT; + tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_GlobalRNC_ID, (void**)&ranaP_GlobalRNCID_p); + if (tempDecoded < 0) { + RANAP_DEBUG("Decoding of IE globalRNC_ID failed\n"); + return -1; + } + decoded += tempDecoded; + if (asn1_xer_print) + xer_fprint(stdout, &asn_DEF_RANAP_GlobalRNC_ID, ranaP_GlobalRNCID_p); + memcpy(&resetIEs->globalRNC_ID, ranaP_GlobalRNCID_p, sizeof(RANAP_GlobalRNC_ID_t)); +#endif + } break; + default: + RANAP_DEBUG("Unknown protocol IE id (%d) for message reseties\n", (int)ie_p->id); + return -1; + } + } + return decoded; +} + +int ranap_encode_resetacknowledgeies( + RANAP_ResetAcknowledge_t *resetAcknowledge, + RANAP_ResetAcknowledgeIEs_t *resetAcknowledgeIEs) { + + RANAP_IE_t *ie; + + if ((ie = ranap_new_ie(RANAP_ProtocolIE_ID_id_CN_DomainIndicator, + RANAP_Criticality_reject, + &asn_DEF_RANAP_CN_DomainIndicator, + &resetAcknowledgeIEs->cN_DomainIndicator)) == NULL) { + return -1; + } + ASN_SEQUENCE_ADD(&resetAcknowledge->resetAcknowledge_ies.list, ie); + + /* Optional field */ + if ((resetAcknowledgeIEs->presenceMask & RESETACKNOWLEDGEIES_RANAP_CRITICALITYDIAGNOSTICS_PRESENT) + == RESETACKNOWLEDGEIES_RANAP_CRITICALITYDIAGNOSTICS_PRESENT) { + if ((ie = ranap_new_ie(RANAP_ProtocolIE_ID_id_CriticalityDiagnostics, + RANAP_Criticality_ignore, + &asn_DEF_RANAP_CriticalityDiagnostics, + &resetAcknowledgeIEs->criticalityDiagnostics)) == NULL) { + return -1; + } + ASN_SEQUENCE_ADD(&resetAcknowledge->resetAcknowledge_ies.list, ie); + } + + /* Optional field */ + if ((resetAcknowledgeIEs->presenceMask & RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT) + == RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT) { + if ((ie = ranap_new_ie(RANAP_ProtocolIE_ID_id_GlobalRNC_ID, + RANAP_Criticality_ignore, + &asn_DEF_RANAP_GlobalRNC_ID, + &resetAcknowledgeIEs->globalRNC_ID)) == NULL) { + return -1; + } + ASN_SEQUENCE_ADD(&resetAcknowledge->resetAcknowledge_ies.list, ie); + } + + return 0; +} + +/*********************************************************************** + * END auto-generated copy+pasted + ***********************************************************************/ + +#if 0 +{ + RANAP_ResetAcknowledgeIEs_s ies; + + memset(&ies, 0, sizeof(ies)); + ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_cs_domain; + + rc = ranap_encoderesetacknowledgeise(&ies, FIXME); +} +#endif + +static int ranap_rx_init_reset(struct hnb_context *hnb, ANY_t *in) +{ + RANAP_ResetIEs_t ies; + int rc; + + rc = ranap_decode_reseties(&ies, in); + if (rc < 0) + return rc; + + DEBUGP(DMAIN, "RESET.req\n"); + + return 0; +} + +static int ranap_rx_initiating_msg(struct hnb_context *hnb, RANAP_InitiatingMessage_t *imsg) +{ + int rc; + + switch (imsg->procedureCode) { + case RANAP_ProcedureCode_id_Reset: + rc = ranap_rx_init_reset(hnb, &imsg->value); + break; + } +} + +static int _hnbgw_ranap_rx(struct hnb_context *hnb, RANAP_RANAP_PDU_t *pdu) +{ + int rc; + + switch (pdu->present) { + case RANAP_RANAP_PDU_PR_initiatingMessage: + rc = ranap_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage); + break; + case RANAP_RANAP_PDU_PR_successfulOutcome: + break; + case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: + break; + default: + break; + } +} + + +int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len) +{ + RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu; + asn_dec_rval_t dec_ret; + int rc; + + memset(pdu, 0, sizeof(*pdu)); + dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu, + data, len, 0, 0); + if (dec_ret.code != RC_OK) { + LOGP(DMAIN, LOGL_ERROR, "Error in RANAP ASN.1 decode\n"); + return rc; + } + + rc = _hnbgw_ranap_rx(msg->dst, pdu); + + return rc; +} + +int hnbgw_ranap_init(void) +{ + +} diff --git a/src/hnbgw_ranap.h b/src/hnbgw_ranap.h new file mode 100644 index 00000000..85a2f983 --- /dev/null +++ b/src/hnbgw_ranap.h @@ -0,0 +1,6 @@ +#pragma once + +#include "hnbgw.h" + +int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len); +int hnbgw_ranap_init(void); diff --git a/src/hnbgw_rua.c b/src/hnbgw_rua.c index a5e46f06..3af564ba 100644 --- a/src/hnbgw_rua.c +++ b/src/hnbgw_rua.c @@ -8,6 +8,7 @@ #include "asn1helpers.h" #include "hnbgw.h" +#include "hnbgw_ranap.h" #include "rua_common.h" #include "rua_ies_defs.h" @@ -87,7 +88,7 @@ static char *rua_cause_str(RUA_Cause_t *cause) } -static int rua_rx_init_connect(struct hnb_context *hnb, ANY_t *in) +static int rua_rx_init_connect(struct msgb *msg, ANY_t *in) { RUA_ConnectIEs_t ies; uint32_t context_id; @@ -102,9 +103,10 @@ static int rua_rx_init_connect(struct hnb_context *hnb, ANY_t *in) DEBUGP(DMAIN, "Connect.req(ctx=0x%x, %s)\n", context_id, ies.establishment_Cause == RUA_Establishment_Cause_emergency_call ? "emergency" : "normal"); + /* FIXME */ } -static int rua_rx_init_disconnect(struct hnb_context *hnb, ANY_t *in) +static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in) { RUA_DisconnectIEs_t ies; uint32_t context_id; @@ -118,9 +120,10 @@ static int rua_rx_init_disconnect(struct hnb_context *hnb, ANY_t *in) DEBUGP(DMAIN, "Disconnect.req(ctx=0x%x,cause=%s)\n", context_id, rua_cause_str(&ies.cause)); + /* FIXME */ } -static int rua_rx_init_dt(struct hnb_context *hnb, ANY_t *in) +static int rua_rx_init_dt(struct msgb *msg, ANY_t *in) { RUA_DirectTransferIEs_t ies; uint32_t context_id; @@ -133,10 +136,11 @@ static int rua_rx_init_dt(struct hnb_context *hnb, ANY_t *in) context_id = asn1bitstr_to_u32(&ies.context_ID); DEBUGP(DMAIN, "Data.req(ctx=0x%x)\n", context_id); + /* FIXME */ } -static int rua_rx_init_udt(struct hnb_context *hnb, ANY_t *in) +static int rua_rx_init_udt(struct msgb *msg, ANY_t *in) { RUA_ConnectionlessTransferIEs_t ies; int rc; @@ -147,9 +151,15 @@ static int rua_rx_init_udt(struct hnb_context *hnb, ANY_t *in) DEBUGP(DMAIN, "UData.req()\n"); + /* FIXME: pass on to RANAP */ + rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size); + /* FIXME: what to do with the asn1c-allocated memory */ + + return rc; } -static int rua_rx_init_err_ind(struct hnb_context *hnb, ANY_t *in) + +static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in) { RUA_ErrorIndicationIEs_t ies; int rc; @@ -160,25 +170,25 @@ static int rua_rx_init_err_ind(struct hnb_context *hnb, ANY_t *in) } -static int rua_rx_initiating_msg(struct hnb_context *hnb, RUA_InitiatingMessage_t *imsg) +static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg) { int rc; switch (imsg->procedureCode) { case RUA_ProcedureCode_id_Connect: - rc = rua_rx_init_connect(hnb, &imsg->value); + rc = rua_rx_init_connect(msg, &imsg->value); break; case RUA_ProcedureCode_id_DirectTransfer: - rc = rua_rx_init_dt(hnb, &imsg->value); + rc = rua_rx_init_dt(msg, &imsg->value); break; case RUA_ProcedureCode_id_Disconnect: - rc = rua_rx_init_disconnect(hnb, &imsg->value); + rc = rua_rx_init_disconnect(msg, &imsg->value); break; case RUA_ProcedureCode_id_ConnectionlessTransfer: - rc = rua_rx_init_udt(hnb, &imsg->value); + rc = rua_rx_init_udt(msg, &imsg->value); break; case RUA_ProcedureCode_id_ErrorIndication: - rc = rua_rx_init_err_ind(hnb, &imsg->value); + rc = rua_rx_init_err_ind(msg, &imsg->value); break; case RUA_ProcedureCode_id_privateMessage: break; @@ -187,18 +197,18 @@ static int rua_rx_initiating_msg(struct hnb_context *hnb, RUA_InitiatingMessage_ } } -static int rua_rx_successful_outcome_msg(struct hnb_context *hnb, RUA_SuccessfulOutcome_t *msg) +static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in) { } -static int rua_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, RUA_UnsuccessfulOutcome_t *msg) +static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in) { } -static int _hnbgw_rua_rx(struct hnb_context *hnb, RUA_RUA_PDU_t *pdu) +static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu) { int rc; @@ -206,13 +216,13 @@ static int _hnbgw_rua_rx(struct hnb_context *hnb, RUA_RUA_PDU_t *pdu) * that's not possible */ switch (pdu->present) { case RUA_RUA_PDU_PR_initiatingMessage: - rc = rua_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage); + rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage); break; case RUA_RUA_PDU_PR_successfulOutcome: - rc = rua_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome); + rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome); break; case RUA_RUA_PDU_PR_unsuccessfulOutcome: - rc = rua_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome); + rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome); break; default: return -1; @@ -235,7 +245,7 @@ int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg) return rc; } - rc = _hnbgw_rua_rx(hnb, pdu); + rc = _hnbgw_rua_rx(msg, pdu); return rc; } diff --git a/src/ranap_common.c b/src/ranap_common.c index 03cad64e..7be7c958 100644 --- a/src/ranap_common.c +++ b/src/ranap_common.c @@ -2,7 +2,10 @@ #include -#include "ranap_common.h" +//#include "ranap_common.h" +#include "ranap/RANAP_RANAP-PDU.h" +#include "ranap/RANAP_ProtocolIE-ID.h" +#include "ranap/RANAP_IE.h" #include "hnbgw.h" extern int asn1_xer_print; diff --git a/src/ranap_common.h b/src/ranap_common.h index 38470539..5bc2841d 100644 --- a/src/ranap_common.h +++ b/src/ranap_common.h @@ -539,6 +539,6 @@ struct msgb *ranap_generate_successful_outcome( asn_TYPE_descriptor_t * td, void *sptr); -RANAP_IE_t *rua_new_ie(RANAP_ProtocolIE_ID_t id, RANAP_Criticality_t criticality, - asn_TYPE_descriptor_t *type, void *sptr); +RANAP_IE_t *ranap_new_ie(RANAP_ProtocolIE_ID_t id, RANAP_Criticality_t criticality, + asn_TYPE_descriptor_t *type, void *sptr);