osmith submitted this change.
vlr: Stop silent call before deduping subscribers
Before this fix, A use count mismatch could be reached by:
* Completing a location updating procedure with TMSI.
* Disconnecting from the BTS.
* Starting a silent call from the MSC.
* Registering again with the same IMSI but a different TMSI.
This would cause the a new subscriber to be created without
the silent call use count, which in turn would cause the
assert in `vlr_subscr_put` in `trans_free` to fail with use count of -1.
Change-Id: If23f8b0e42d4a3a8bf1c8f5ca81b045834b6cccd
---
M include/osmocom/msc/silent_call.h
M src/libmsc/silent_call.c
M src/libvlr/vlr.c
3 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/include/osmocom/msc/silent_call.h b/include/osmocom/msc/silent_call.h
index fb53e90..6aea4c6 100644
--- a/include/osmocom/msc/silent_call.h
+++ b/include/osmocom/msc/silent_call.h
@@ -10,6 +10,7 @@
struct vty *vty);
extern int gsm_silent_call_stop(struct vlr_subscr *vsub);
+extern int gsm_silent_call_is_ongoing(struct vlr_subscr *vsub);
void trans_silent_call_free(struct gsm_trans *trans);
diff --git a/src/libmsc/silent_call.c b/src/libmsc/silent_call.c
index 327ed7f..9b89a62 100644
--- a/src/libmsc/silent_call.c
+++ b/src/libmsc/silent_call.c
@@ -186,3 +186,13 @@
trans_free(trans);
return 0;
}
+
+/* Does the subscriber have an ongoing silent call transaction? */
+int gsm_silent_call_is_ongoing(struct vlr_subscr *vsub)
+{
+ struct msc_a *msc_a = msc_a_for_vsub(vsub, true);
+ if (!msc_a)
+ return false;
+
+ return trans_find_by_type(msc_a, TRANS_SILENT_CALL) != NULL;
+}
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index c9055dc..21f9fc6 100644
--- a/src/libvlr/vlr.c
+++ b/src/libvlr/vlr.c
@@ -36,6 +36,7 @@
#include <osmocom/vlr/vlr.h>
#include <osmocom/gsupclient/gsup_client_mux.h>
#include <osmocom/msc/paging.h>
+#include <osmocom/msc/silent_call.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -642,6 +643,12 @@
if (!strcmp(vsub->imsi, imsi))
return;
+ /* If the same subscriber has silent call (probably pending) stop the silent call to prevent
+ * use count mismatch when freeing the transaction. */
+ exists = vlr_subscr_find_by_imsi(vsub->vlr, imsi, NULL);
+ if (gsm_silent_call_is_ongoing(exists))
+ gsm_silent_call_stop(exists);
+
/* We've just learned about this new IMSI, our primary key in the VLR. make sure to invalidate any prior VLR
* entries for this IMSI. */
exists = vlr_subscr_find_by_imsi(vsub->vlr, imsi, NULL);
To view, visit change 41131. To unsubscribe, or for help writing mail filters, visit settings.