neels has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-sccp/+/32320 )
Change subject: sccp_scoc.c: fix infinite loop on conn ID exhaustion
......................................................................
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
---
M src/sccp_scoc.c
1 file changed, 52 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/20/32320/1
diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c
index c929ed6..6d2499c 100644
--- a/src/sccp_scoc.c
+++ b/src/sccp_scoc.c
@@ -539,10 +539,19 @@
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 *must* check the returned value, even if max_attempts == 0: on negative return
value, there are no unused IDs
+ * available.
+ * \param[in] sccp The SCCP instance to determine a new connection ID for.
+ * \param[in] max_attempts Number of iterations to find an unused ID, or zero to iterate
the entire ID number space.
+ * \return unused ID on success (>=0) or negative on elapsed max_attempts without an
unused id (<0).
+ */
+static int osmo_sccp_instance_next_conn_id(struct osmo_sccp_instance *sccp, uint32_t
max_attempts)
{
- struct osmo_sccp_instance *sccp = user->inst;
+ if (!max_attempts || max_attempts > 0x00FFFFFE) {
+ /* Maximally iterate the entire conn id number space once. */
+ max_attempts = 0x00FFFFFE;
+ }
/* SUA: RFC3868 sec 3.10.4:
* The source reference number is a 4 octet long integer.
@@ -555,14 +564,32 @@
* 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 (1) {
/* 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;
+
+ if (max_attempts) {
+ max_attempts--;
+ if (!max_attempts)
+ break;
+ }
+ }
+
+ 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, 0);
+ if (conn_id < 0)
+ return NULL;
+ return conn_create_id(user, conn_id);
}
static void conn_opt_data_clear_cache(struct sccp_connection *conn)
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-sccp/+/32320
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Change-Id: Ib64e0cb1ae0cc8b7bebcb2a352d4068b496b304a
Gerrit-Change-Number: 32320
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange