diff options
author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2023-04-14 23:33:24 +0200 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2023-05-10 02:17:04 +0200 |
commit | 8bc881f31a5c29734122b3ec1461e42abf6fc7df (patch) | |
tree | 5e9ec4fd8efafc896414e65231a5cfe0c046325d | |
parent | d5139548f237bfab984ac0e0ca3406c42cbd895c (diff) |
sccp_scoc.c: fix infinite loop on conn ID exhaustion
Looking for an unused SCCP connection ID has no exit condition if all
connection IDs are in use. However unlikely it is that there are
16777215 active connections on one SCCP instance, add an exit condition.
Do so by implementing the ID lookup in a new separate function, which
qualifies for public API (upcoming patch).
So far, use an exit condition closest to previous behavior: iterate the
entire SCCP conn id number space before exiting in failure.
Change-Id: Ib64e0cb1ae0cc8b7bebcb2a352d4068b496b304a
-rw-r--r-- | src/sccp_scoc.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c index 1838615..e63ebf8 100644 --- a/src/sccp_scoc.c +++ b/src/sccp_scoc.c @@ -539,10 +539,14 @@ static struct sccp_connection *conn_create_id(struct osmo_sccp_user *user, uint3 return conn; } -/* Search for next free connection ID and allocate conn */ -static struct sccp_connection *conn_create(struct osmo_sccp_user *user) +/* Return an unused SCCP connection ID. + * Callers should check the returned value: on negative return value, there are no unused IDs available. + * \param[in] sccp The SCCP instance to determine a new connection ID for. + * \return unused ID on success (range [0x0, 0x00fffffe]) or negative on elapsed max_attempts without an unused id (<0). + */ +static int osmo_sccp_instance_next_conn_id(struct osmo_sccp_instance *sccp) { - struct osmo_sccp_instance *sccp = user->inst; + int max_attempts = 0x00FFFFFE; /* SUA: RFC3868 sec 3.10.4: * The source reference number is a 4 octet long integer. @@ -555,14 +559,26 @@ static struct sccp_connection *conn_create(struct osmo_sccp_user *user) * Hence, as we currently use the connection ID also as local reference, * let's simply use 24 bit ids to fit all link types (excluding 0x00ffffff). */ - do { + while (OSMO_LIKELY((max_attempts--) > 0)) { /* Optimized modulo operation (% 0x00FFFFFE) using bitwise AND plus CMP: */ sccp->next_id = (sccp->next_id + 1) & 0x00FFFFFF; if (OSMO_UNLIKELY(sccp->next_id == 0x00FFFFFF)) sccp->next_id = 0; - } while (conn_find_by_id(sccp, sccp->next_id)); - return conn_create_id(user, sccp->next_id); + if (!conn_find_by_id(sccp, sccp->next_id)) + return sccp->next_id; + } + + return -1; +} + +/* Search for next free connection ID and allocate conn */ +static struct sccp_connection *conn_create(struct osmo_sccp_user *user) +{ + int conn_id = osmo_sccp_instance_next_conn_id(user->inst); + if (conn_id < 0) + return NULL; + return conn_create_id(user, conn_id); } static void conn_opt_data_clear_cache(struct sccp_connection *conn) |