aboutsummaryrefslogtreecommitdiffstats
path: root/src/hnbgw_rua.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hnbgw_rua.c')
-rw-r--r--src/hnbgw_rua.c569
1 files changed, 0 insertions, 569 deletions
diff --git a/src/hnbgw_rua.c b/src/hnbgw_rua.c
deleted file mode 100644
index 71c3f8e..0000000
--- a/src/hnbgw_rua.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/* hnb-gw specific code for RUA (Ranap User Adaption) */
-
-/* (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 <osmocom/core/msgb.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/netif/stream.h>
-
-#include <osmocom/sigtran/sccp_sap.h>
-#include <osmocom/sigtran/sccp_helpers.h>
-
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-
-#include "asn1helpers.h"
-
-#include <osmocom/iuh/hnbgw.h>
-#include <osmocom/iuh/hnbgw_ranap.h>
-#include <osmocom/rua/rua_common.h>
-#include <osmocom/rua/rua_ies_defs.h>
-#include <osmocom/iuh/context_map.h>
-#include <osmocom/hnbap/CN-DomainIndicator.h>
-
-static const char *cn_domain_indicator_to_str(CN_DomainIndicator_t cN_DomainIndicator)
-{
- switch (cN_DomainIndicator) {
- case RUA_CN_DomainIndicator_cs_domain:
- return "IuCS";
- case RUA_CN_DomainIndicator_ps_domain:
- return "IuPS";
- default:
- return "(unknown-domain)";
- }
-}
-
-static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
-{
- if (!msg)
- return -EINVAL;
-
- msgb_sctp_ppid(msg) = IUH_PPI_RUA;
- osmo_stream_srv_send(ctx->conn, msg);
-
- return 0;
-}
-
-int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
-{
- RUA_ConnectionlessTransfer_t out;
- RUA_ConnectionlessTransferIEs_t ies;
- struct msgb *msg;
- int rc;
-
- memset(&ies, 0, sizeof(ies));
- ies.ranaP_Message.buf = (uint8_t *) data;
- ies.ranaP_Message.size = len;
-
- /* FIXME: msgb_free(msg)? ownership not yet clear */
-
- memset(&out, 0, sizeof(out));
- rc = rua_encode_connectionlesstransferies(&out, &ies);
- if (rc < 0)
- return rc;
-
- msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
- RUA_Criticality_reject,
- &asn_DEF_RUA_ConnectionlessTransfer,
- &out);
- ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
-
- DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
-
- return hnbgw_rua_tx(hnb, msg);
-}
-
-int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
- const uint8_t *data, unsigned int len)
-{
- RUA_DirectTransfer_t out;
- RUA_DirectTransferIEs_t ies;
- uint32_t ctxidbuf;
- struct msgb *msg;
- int rc;
-
- memset(&ies, 0, sizeof(ies));
- if (is_ps)
- ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
- else
- ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
- asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
- ies.ranaP_Message.buf = (uint8_t *) data;
- ies.ranaP_Message.size = len;
-
- /* FIXME: msgb_free(msg)? ownership not yet clear */
-
- memset(&out, 0, sizeof(out));
- rc = rua_encode_directtransferies(&out, &ies);
- if (rc < 0)
- return rc;
-
- msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
- RUA_Criticality_reject,
- &asn_DEF_RUA_DirectTransfer,
- &out);
- ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
-
- DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
- is_ps ? "ps" : "cs", msgb_length(msg));
-
- return hnbgw_rua_tx(hnb, msg);
-}
-
-int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
- const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
-{
- RUA_Disconnect_t out;
- RUA_DisconnectIEs_t ies;
- struct msgb *msg;
- uint32_t ctxidbuf;
- int rc;
-
- memset(&ies, 0, sizeof(ies));
- if (is_ps)
- ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
- else
- ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
- asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
- memcpy(&ies.cause, cause, sizeof(ies.cause));
- if (data && len) {
- ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
- ies.ranaP_Message.buf = (uint8_t *) data;
- ies.ranaP_Message.size = len;
- }
-
- /* FIXME: msgb_free(msg)? ownership not yet clear */
-
- memset(&out, 0, sizeof(out));
- rc = rua_encode_disconnecties(&out, &ies);
- if (rc < 0)
- return rc;
-
- msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
- RUA_Criticality_reject,
- &asn_DEF_RUA_Disconnect,
- &out);
- ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
-
- DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
- is_ps ? "ps" : "cs", msgb_length(msg));
-
-
- return hnbgw_rua_tx(hnb, msg);
-}
-
-
-
-/* forward a RUA message to the SCCP User API to SCCP */
-static int rua_to_scu(struct hnb_context *hnb,
- CN_DomainIndicator_t cN_DomainIndicator,
- enum osmo_scu_prim_type type,
- uint32_t context_id, uint32_t cause,
- const uint8_t *data, unsigned int len)
-{
- struct msgb *msg;
- struct osmo_scu_prim *prim;
- struct hnbgw_context_map *map = NULL;
- struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
- struct osmo_sccp_addr *remote_addr;
- bool is_ps;
- bool release_context_map = false;
- int rc;
-
- switch (cN_DomainIndicator) {
- case RUA_CN_DomainIndicator_cs_domain:
- remote_addr = &hnb->gw->sccp.iucs_remote_addr;
- is_ps = false;
- break;
- case RUA_CN_DomainIndicator_ps_domain:
- remote_addr = &hnb->gw->sccp.iups_remote_addr;
- is_ps = true;
- break;
- default:
- LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %ld\n",
- cN_DomainIndicator);
- return -1;
- }
-
- if (!cn) {
- DEBUGP(DRUA, "CN=NULL, discarding message\n");
- return 0;
- }
-
- msg = msgb_alloc(1500, "rua_to_sccp");
-
- prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
- osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);
-
- switch (type) {
- case OSMO_SCU_PRIM_N_UNITDATA:
- DEBUGP(DRUA, "rua_to_scu() %s to %s, rua_ctx_id %u (unitdata, no scu_conn_id)\n",
- cn_domain_indicator_to_str(cN_DomainIndicator),
- osmo_sccp_addr_dump(remote_addr),
- context_id);
- break;
- default:
- map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn);
- OSMO_ASSERT(map);
- DEBUGP(DRUA, "rua_to_scu() %s to %s, rua_ctx_id %u scu_conn_id %u\n",
- cn_domain_indicator_to_str(cN_DomainIndicator),
- osmo_sccp_addr_dump(remote_addr),
- map->rua_ctx_id, map->scu_conn_id);
- }
-
- /* add primitive header */
- switch (type) {
- case OSMO_SCU_PRIM_N_CONNECT:
- prim->u.connect.called_addr = *remote_addr;
- prim->u.connect.calling_addr = cn->gw->sccp.local_addr;
- prim->u.connect.sccp_class = 2;
- prim->u.connect.conn_id = map->scu_conn_id;
- /* Two separate logs because of osmo_sccp_addr_dump(). */
- DEBUGP(DRUA, "RUA to SCCP N_CONNECT: called_addr:%s\n",
- osmo_sccp_addr_dump(&prim->u.connect.called_addr));
- DEBUGP(DRUA, "RUA to SCCP N_CONNECT: calling_addr:%s\n",
- osmo_sccp_addr_dump(&prim->u.connect.calling_addr));
- break;
- case OSMO_SCU_PRIM_N_DATA:
- prim->u.data.conn_id = map->scu_conn_id;
- break;
- case OSMO_SCU_PRIM_N_DISCONNECT:
- prim->u.disconnect.conn_id = map->scu_conn_id;
- prim->u.disconnect.cause = cause;
- release_context_map = true;
- break;
- case OSMO_SCU_PRIM_N_UNITDATA:
- prim->u.unitdata.called_addr = *remote_addr;
- prim->u.unitdata.calling_addr = cn->gw->sccp.local_addr;
- /* Two separate logs because of osmo_sccp_addr_dump(). */
- DEBUGP(DRUA, "RUA to SCCP N_UNITDATA: called_addr:%s\n",
- osmo_sccp_addr_dump(&prim->u.unitdata.called_addr));
- DEBUGP(DRUA, "RUA to SCCP N_UNITDATA: calling_addr:%s\n",
- osmo_sccp_addr_dump(&prim->u.unitdata.calling_addr));
- break;
- default:
- return -EINVAL;
- }
-
- /* add optional data section, if needed */
- if (data && len) {
- msg->l2h = msgb_put(msg, len);
- memcpy(msg->l2h, data, len);
- }
-
- rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
-
- if (map && release_context_map)
- context_map_deactivate(map);
-
- return rc;
-}
-
-static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
-{
- /* FIXME: Implement this! */
-#if 0
- switch (in->present) {
- case RUA_Cause_PR_NOTHING:
- break;
- case RUA_Cause_PR_radioNetwork:
- switch (in->choice.radioNetwork) {
- case RUA_CauseRadioNetwork_normal:
- case RUA_CauseRadioNetwork_connect_failed:
- case RUA_CauseRadioNetwork_network_release:
- case RUA_CauseRadioNetwork_unspecified:
- }
- break;
- case RUA_Cause_PR_transport:
- switch (in->choice.transport) {
- case RUA_CauseTransport_transport_resource_unavailable:
- break;
- case RUA_CauseTransport_unspecified:
- break;
- }
- break;
- case RUA_Cause_PR_protocol:
- switch (in->choice.protocol) {
- case RUA_CauseProtocol_transfer_syntax_error:
- break;
- case RUA_CauseProtocol_abstract_syntax_error_reject:
- break;
- case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify:
- break;
- case RUA_CauseProtocol_message_not_compatible_with_receiver_state:
- break;
- case RUA_CauseProtocol_semantic_error:
- break;
- case RUA_CauseProtocol_unspecified:
- break;
- case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
- break;
- }
- break;
- case RUA_Cause_PR_misc:
- switch (in->choice.misc) {
- case RUA_CauseMisc_processing_overload:
- break;
- case RUA_CauseMisc_hardware_failure:
- break;
- case RUA_CauseMisc_o_and_m_intervention:
- break;
- case RUA_CauseMisc_unspecified:
- break;
- }
- break;
- default:
- break;
- }
-#else
- return 0;
-#endif
-
-}
-
-static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
-{
- RUA_ConnectIEs_t ies;
- struct hnb_context *hnb = msg->dst;
- uint32_t context_id;
- int rc;
-
- rc = rua_decode_connecties(&ies, in);
- if (rc < 0)
- return rc;
-
- context_id = asn1bitstr_to_u24(&ies.context_ID);
-
- DEBUGP(DRUA, "RUA %s Connect.req(ctx=0x%x, %s)\n",
- cn_domain_indicator_to_str(ies.cN_DomainIndicator),
- context_id,
- ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
- ? "emergency" : "normal");
-
- rc = rua_to_scu(hnb, ies.cN_DomainIndicator, OSMO_SCU_PRIM_N_CONNECT,
- context_id, 0, ies.ranaP_Message.buf,
- ies.ranaP_Message.size);
-
- rua_free_connecties(&ies);
-
- return rc;
-}
-
-static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
-{
- RUA_DisconnectIEs_t ies;
- struct hnb_context *hnb = msg->dst;
- uint32_t context_id;
- uint32_t scu_cause;
- uint8_t *ranap_data = NULL;
- unsigned int ranap_len = 0;
- int rc;
-
- rc = rua_decode_disconnecties(&ies, in);
- if (rc < 0)
- return rc;
-
- context_id = asn1bitstr_to_u24(&ies.context_ID);
- scu_cause = rua_to_scu_cause(&ies.cause);
-
- DEBUGP(DRUA, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
- rua_cause_str(&ies.cause));
-
- if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) {
- ranap_data = ies.ranaP_Message.buf;
- ranap_len = ies.ranaP_Message.size;
- }
-
- rc = rua_to_scu(hnb, ies.cN_DomainIndicator,
- OSMO_SCU_PRIM_N_DISCONNECT,
- context_id, scu_cause, ranap_data, ranap_len);
-
- rua_free_disconnecties(&ies);
-
- return rc;
-}
-
-static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
-{
- RUA_DirectTransferIEs_t ies;
- struct hnb_context *hnb = msg->dst;
- uint32_t context_id;
- int rc;
-
- rc = rua_decode_directtransferies(&ies, in);
- if (rc < 0)
- return rc;
-
- context_id = asn1bitstr_to_u24(&ies.context_ID);
-
- DEBUGP(DRUA, "RUA Data.req(ctx=0x%x)\n", context_id);
-
- rc = rua_to_scu(hnb,
- ies.cN_DomainIndicator,
- OSMO_SCU_PRIM_N_DATA,
- context_id, 0, ies.ranaP_Message.buf,
- ies.ranaP_Message.size);
-
- rua_free_directtransferies(&ies);
-
- return rc;
-}
-
-static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
-{
- RUA_ConnectionlessTransferIEs_t ies;
- int rc;
-
- rc = rua_decode_connectionlesstransferies(&ies, in);
- if (rc < 0)
- return rc;
-
- DEBUGP(DRUA, "RUA UData.req()\n");
-
- /* according tot the spec, we can primarily receive Overload,
- * Reset, Reset ACK, Error Indication, reset Resource, Reset
- * Resurce Acknowledge as connecitonless RANAP. There are some
- * more messages regarding Information Transfer, Direct
- * Information Transfer and Uplink Information Trnansfer that we
- * can ignore. In either case, it is RANAP that we need to
- * decode... */
- rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
- rua_free_connectionlesstransferies(&ies);
-
- return rc;
-}
-
-
-static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
-{
- RUA_ErrorIndicationIEs_t ies;
- int rc;
-
- rc = rua_decode_errorindicationies(&ies, in);
- if (rc < 0)
- return rc;
-
- LOGP(DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n",
- rua_cause_str(&ies.cause));
-
- rua_free_errorindicationies(&ies);
- return rc;
-}
-
-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(msg, &imsg->value);
- break;
- case RUA_ProcedureCode_id_DirectTransfer:
- rc = rua_rx_init_dt(msg, &imsg->value);
- break;
- case RUA_ProcedureCode_id_Disconnect:
- rc = rua_rx_init_disconnect(msg, &imsg->value);
- break;
- case RUA_ProcedureCode_id_ConnectionlessTransfer:
- rc = rua_rx_init_udt(msg, &imsg->value);
- break;
- case RUA_ProcedureCode_id_ErrorIndication:
- rc = rua_rx_init_err_ind(msg, &imsg->value);
- break;
- case RUA_ProcedureCode_id_privateMessage:
- LOGP(DRUA, LOGL_NOTICE,
- "Unhandled: RUA Initiating Msg: Private Msg\n");
- rc = 0;
- break;
- default:
- LOGP(DRUA, LOGL_NOTICE, "Unknown RUA Procedure %lu\n",
- imsg->procedureCode);
- rc = -1;
- }
-
- return rc;
-}
-
-static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
-{
- /* FIXME */
- LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Successful Outcome\n");
- return -1;
-}
-
-static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
-{
- /* FIXME */
- LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n");
- return -1;
-}
-
-
-static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
-{
- int rc;
-
- /* it's a bit odd that we can't dispatch on procedure code, but
- * that's not possible */
- switch (pdu->present) {
- case RUA_RUA_PDU_PR_initiatingMessage:
- rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
- break;
- case RUA_RUA_PDU_PR_successfulOutcome:
- rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
- break;
- case RUA_RUA_PDU_PR_unsuccessfulOutcome:
- rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
- break;
- default:
- LOGP(DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present);
- rc = -1;
- }
-
- return rc;
-}
-
-int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
-{
- RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
- asn_dec_rval_t dec_ret;
- int rc;
-
- /* decode and handle to _hnbgw_hnbap_rx() */
-
- memset(pdu, 0, sizeof(*pdu));
- dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
- msg->data, msgb_length(msg), 0, 0);
- if (dec_ret.code != RC_OK) {
- LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
- return -1;
- }
-
- rc = _hnbgw_rua_rx(msg, pdu);
-
- return rc;
-}
-
-
-int hnbgw_rua_init(void)
-{
- return 0;
-}