osmo-iuh/src/hnbgw_rua.c

559 lines
14 KiB
C
Raw Normal View History

/* 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 <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);
2015-12-26 22:40:31 +00:00
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);
2015-12-26 22:40:31 +00:00
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;
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
struct osmo_sccp_addr *remote_addr;
bool is_ps;
int rc;
switch (cN_DomainIndicator) {
case RUA_CN_DomainIndicator_cs_domain:
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
remote_addr = &hnb->gw->sccp.remote_addr_cs;
is_ps = false;
break;
case RUA_CN_DomainIndicator_ps_domain:
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
remote_addr = &hnb->gw->sccp.remote_addr_ps;
is_ps = true;
break;
default:
LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %u\n",
cN_DomainIndicator);
return -1;
}
2015-12-29 18:00:35 +00:00
if (!cn) {
DEBUGP(DRUA, "CN=NULL, discarding message\n");
return 0;
}
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
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);
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
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:
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
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;
break;
case OSMO_SCU_PRIM_N_UNITDATA:
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
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);
}
migrate osmo-hnbgw to libosmo-sigtran's SCCP/M3UA libosmo-sigtran now has a "proper" SCCP/M3UA stack, so we can make our hnb-gw 3GPP compliant by switching from the old SUA code to the new universal SCCP user API with support for (currently) M3UA and SUA. Main changes: Use one cn_link to STP: We will connect to the core network using an (Osmo)STP instance that routes to MSC and SGSN, so we want one SCCP link instead of two. The only difference between IuCS and IuPS is a different remote osmo_sccp_addr. This has various effects through the messaging code; the patch is a bit larger than I would like, but it is hard to separate out truly independent smaller changes. CS or PS domain was previously flagged in the separate cn_link, as ctx pointer for two separate sccp_sap_up()s. Now there's just one such ctx, so determine is_ps from the RANAP Domain Indicator, or from the conn's hnbgw_context_map: - Add is_ps to context_map_alloc_by_hnb(). - To find a matching context, the RUA ID alone is no longer sufficient, also match is_ps (possible optimization todo: separate lists). We would send separate CS or PS Reset messages based on the cn_link, instead send both CS and PS Reset at the same time for the single cn_link. This could be adjusted to detect presence of MSC or SGSN instead. Pending: adjust the VTY config to reflect that there is only one remote address. Place a TODO comment for that. Smaller changes: rua_to_scu(): populate called and calling addresses for N_CONNECT and N_UNITDATA. Remove DSUA. Don't build dummy_cn, which is still implemented on SUA. Mark todo to maybe re-include it based on M3UA later. In hnbgw_cnlink, place sccp related items in a separate sub-struct. Do not keep an llist of cn_links, just have the one. Remove iteration and list management. Change jenkins script to build libosmo-sccp master. Patch-by: hwelte, nhofmeyr Change-Id: I8ac15fa2fd25bedb26297177e416976a5389b573
2017-07-03 14:49:43 +00:00
rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
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);
/* FIXME: what to do with the asn1c-allocated memory */
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);
/* FIXME: what to do with the asn1c-allocated memory */
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);
/* FIXME: what to do with the asn1c-allocated memory */
rua_free_directtransferies(&ies);
return rc;
}
static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
{
RUA_ConnectionlessTransferIEs_t ies;
RUA_CN_DomainIndicator_t domain;
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 %u\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 Sucessful 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;
}