summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Smith <osmith@sysmocom.de>2019-04-03 09:52:19 +0200
committerOliver Smith <osmith@sysmocom.de>2019-04-04 08:40:05 +0200
commit8e75e6388c93ea2dc2e9ad1a08989b603ac5cbf2 (patch)
treec7f4ddac328494815a6219e99207c817a9e78be7
parent49eea32ab4158b2b80a3862513363f237fb49939 (diff)
sccp_scoc: separate conn_id from local_refosmith/conn-id-scoping
Properly generate a local_ref for each connection, that is unique for each SCU user. Previously, the conn_id was used as local_ref. Related: OS#3871 Change-Id: Ifd55c6b7ed2558ff072042079cf45f5068a971de
-rw-r--r--src/sccp_internal.h3
-rw-r--r--src/sccp_scoc.c77
2 files changed, 64 insertions, 16 deletions
diff --git a/src/sccp_internal.h b/src/sccp_internal.h
index ad8a6fd..10ec285 100644
--- a/src/sccp_internal.h
+++ b/src/sccp_internal.h
@@ -78,6 +78,9 @@ struct osmo_sccp_user {
/* Application Server FSM Instance */
struct osmo_fsm_inst *as_fi;
+
+ /* next local reference to allocate */
+ uint32_t next_local_ref;
};
extern int DSCCP;
diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c
index 91a1ab7..2f5be28 100644
--- a/src/sccp_scoc.c
+++ b/src/sccp_scoc.c
@@ -47,6 +47,7 @@
*/
#include <string.h>
+#include <errno.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/linuxlist.h>
@@ -93,6 +94,11 @@ struct sccp_connection {
* it whever sending data to the peer. Only relevant over the
* wire, not to be used across the SCCP user SAP */
uint32_t remote_ref;
+ /* SCCP Local Connection Reference. Generated by the local SCCP stack
+ * (conn_get_unused_local_ref()) to uniquely identify a SCCP connection.
+ * The local_ref is unique for each (SCCP connection, SCU user) tuple. Only
+ * relevant over the wire, not to be used accross the SCCP user SAP. */
+ uint32_t local_ref;
uint32_t importance;
uint32_t sccp_class;
@@ -456,15 +462,49 @@ static struct sccp_connection *conn_find_by_id(struct osmo_sccp_instance *inst,
return NULL;
}
+static struct sccp_connection *conn_find_by_local_ref(struct osmo_sccp_user *user, uint32_t local_ref)
+{
+ struct sccp_connection *conn;
+
+ llist_for_each_entry(conn, &user->inst->connections, list) {
+ if (conn->user == user && conn->local_ref == local_ref)
+ return conn;
+ }
+ return NULL;
+}
+
+static int conn_unused_local_ref(struct osmo_sccp_user *user, uint32_t *local_ref)
+{
+ uint32_t current;
+ uint32_t start = user->next_local_ref;
+
+ do {
+ current = user->next_local_ref++;
+ if (current == start) {
+ LOGP(DLSCCP, LOGL_ERROR, "No unused local reference available for user %s\n", user->name);
+ return -ENOSPC;
+ }
+ } while (conn_find_by_local_ref(user, current));
+
+ *local_ref = current;
+ return 0;
+}
+
#define INIT_TIMER(x, fn, priv) do { (x)->cb = fn; (x)->data = priv; } while (0)
/* allocate + init a SCCP Connection with given ID */
static struct sccp_connection *conn_create_id(struct osmo_sccp_user *user, uint32_t conn_id)
{
- struct sccp_connection *conn = talloc_zero(user->inst, struct sccp_connection);
+ uint32_t local_ref;
+ struct sccp_connection *conn;
char name[16];
+ if (conn_unused_local_ref(user, &local_ref) < 0)
+ return NULL;
+
+ conn = talloc_zero(user->inst, struct sccp_connection);
conn->conn_id = conn_id;
+ conn->local_ref = local_ref;
conn->inst = user->inst;
conn->user = user;
@@ -538,7 +578,7 @@ static struct xua_msg *xua_gen_relre(struct sccp_connection *conn,
xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_RELRE);
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
- xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
+ xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->local_ref);
xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RELEASE | cause);
/* optional: importance */
if (prim && msgb_l2(prim->oph.msg))
@@ -581,7 +621,7 @@ static struct xua_msg *xua_gen_msg_co(struct sccp_connection *conn, uint32_t eve
xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_CORE);
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_PROTO_CLASS, conn->sccp_class);
- xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
+ xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->local_ref);
xua_msg_add_sccp_addr(xua, SUA_IEI_DEST_ADDR, &conn->called_addr);
xua_msg_add_u32(xua, SUA_IEI_SEQ_CTRL, 0); /* TODO */
/* optional: sequence number (class 3 only) */
@@ -597,7 +637,7 @@ static struct xua_msg *xua_gen_msg_co(struct sccp_connection *conn, uint32_t eve
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_PROTO_CLASS, conn->sccp_class);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
- xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
+ xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->local_ref);
xua_msg_add_u32(xua, SUA_IEI_SEQ_CTRL, 0); /* TODO */
/* optional: sequence number (class 3 only) */
if (conn->called_addr.presence)
@@ -618,7 +658,7 @@ static struct xua_msg *xua_gen_msg_co(struct sccp_connection *conn, uint32_t eve
xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_RELRE);
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
- xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
+ xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->local_ref);
xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RELEASE | prim->u.disconnect.cause);
/* optional: importance */
if (prim && msgb_l2(prim->oph.msg) && msgb_l2len(prim->oph.msg))
@@ -629,7 +669,7 @@ static struct xua_msg *xua_gen_msg_co(struct sccp_connection *conn, uint32_t eve
xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_RELCO);
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
- xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
+ xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->local_ref);
/* optional: importance */
break;
case SUA_CO_CODT: /* Connection Oriented Data Transfer == SCCP DT1 */
@@ -647,7 +687,7 @@ static struct xua_msg *xua_gen_msg_co(struct sccp_connection *conn, uint32_t eve
xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_COIT);
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_PROTO_CLASS, conn->sccp_class);
- xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
+ xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->local_ref);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
/* optional: sequence number; credit (both class 3 only) */
break;
@@ -1354,6 +1394,16 @@ static struct osmo_sccp_user *sccp_find_user(struct osmo_sccp_instance *inst,
return sccp_user_find(inst, called_addr.ssn, called_addr.pc);
}
+static struct sccp_connection *sccp_find_connection(struct osmo_sccp_instance *inst, struct xua_msg *xua)
+{
+ uint32_t local_ref = xua_msg_get_u32(xua, SUA_IEI_DEST_REF);
+ struct osmo_sccp_user *user = sccp_find_user(inst, xua);
+
+ if (user)
+ return conn_find_by_local_ref(user, local_ref);
+ return NULL;
+}
+
/*! \brief SCOC: Receive SCRC Routing Failure
* \param[in] inst SCCP Instance on which we operate
* \param[in] xua SUA message that was failed to route
@@ -1361,12 +1411,9 @@ static struct osmo_sccp_user *sccp_find_user(struct osmo_sccp_instance *inst,
void sccp_scoc_rx_scrc_rout_fail(struct osmo_sccp_instance *inst,
struct xua_msg *xua, uint32_t return_cause)
{
- uint32_t conn_id;
- struct sccp_connection *conn;
+ struct sccp_connection *conn = sccp_find_connection(inst, xua);
/* try to dispatch to connection FSM (if any) */
- conn_id = xua_msg_get_u32(xua, SUA_IEI_DEST_REF);
- conn = conn_find_by_id(inst, conn_id);
if (conn) {
osmo_fsm_inst_dispatch(conn->fi,
SCOC_E_RCOC_ROUT_FAIL_IND, xua);
@@ -1626,13 +1673,11 @@ void sccp_scoc_rx_from_scrc(struct osmo_sccp_instance *inst,
conn = conn_create(scu);
conn->incoming = true;
} else {
- uint32_t conn_id;
/* Resolve existing connection */
- conn_id = xua_msg_get_u32(xua, SUA_IEI_DEST_REF);
- conn = conn_find_by_id(inst, conn_id);
+ conn = sccp_find_connection(inst, xua);
if (!conn) {
LOGP(DLSCCP, LOGL_NOTICE, "Cannot find connection for "
- "local reference %u\n", conn_id);
+ "local reference %u\n", xua_msg_get_u32(xua, SUA_IEI_DEST_REF));
sccp_scoc_rx_unass_local_ref(inst, xua);
return;
}
@@ -1641,7 +1686,7 @@ void sccp_scoc_rx_from_scrc(struct osmo_sccp_instance *inst,
OSMO_ASSERT(conn->fi);
DEBUGP(DLSCCP, "Received %s for local reference %u\n",
- xua_hdr_dump(xua, &xua_dialect_sua), conn->conn_id);
+ xua_hdr_dump(xua, &xua_dialect_sua), conn->local_ref);
if (xua->hdr.msg_type != SUA_CO_CORE &&
xua->hdr.msg_type != SUA_CO_COAK &&