fix VLR evil twin on LU with unknown TMSI

When a subscriber first attaches by TMSI only, and later tells the IMSI
via ID Response, it may turn out that this IMSI already exists in the
VLR database. If this happens, the TMSI that the subscriber issued was
not known in the existing VLR entry, indicating that the subscriber has
in the meantime camped on a different core. Which means we can assume
that there cannot be any active connections, and the old subscriber can
be discarded, for the benefit of the new one.

(We could also discard the new one, but it is more complex to reparent
the ongoing FSMs for Compl L3 than to copy some dormant VLR state.)

In vlr_subscr_set_imsi(), check for an existing IMSI entry in the VLR.

If such exists, copy any pending Paging and auth tuple state to the new
subscriber, and discard the old one from the VLR.

In order to safely discard a vlr subscriber by force, add a new vlr_ops
function: subscr_inval(), to tell the MSC that a vlr_subscr is no longer
valid.

Upcoming patch I583682d1a35a70b008d7bb2d89ba7c3109a60b21 better clears
TMSI state from the VLR, making it more likely to hit the evil twin
situation this patch fixes; hence this is, sort of, preparation.

Related: SYS#6860 OS#4721
Change-Id: Ifdabe0b65bffafbf7b8e5cc10e2d225d1ed1cecd
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 70faf95..17350fa 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -1572,6 +1572,24 @@
 	return 0;
 }
 
+static void msc_vlr_subscr_inval(void *msc_conn_ref, struct vlr_subscr *vsub)
+{
+	/* Search vsub backwards to make sure msc_conn_ref is a valid msc_a instance. */
+	struct msub *msub;
+	OSMO_ASSERT(vsub);
+	llist_for_each_entry(msub, &msub_list, entry) {
+		struct msc_a *msc_a;
+		if (msub->vsub != vsub)
+			continue;
+
+		msc_a = msub_msc_a(msub);
+		if (msc_a)
+			msc_a_release_cn(msc_a);
+
+		msub->vsub = NULL;
+	}
+}
+
 /* operations that we need to implement for libvlr */
 const struct vlr_ops msc_vlr_ops = {
 	.tx_auth_req = msc_vlr_tx_auth_req,
@@ -1586,6 +1604,7 @@
 	.tx_mm_info = msc_vlr_tx_mm_info,
 	.subscr_update = msc_vlr_subscr_update,
 	.subscr_assoc = msc_vlr_subscr_assoc,
+	.subscr_inval = msc_vlr_subscr_inval,
 };
 
 struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value)