sgsn: Re-add searching for MM ctx based on TLLI / P-TMSI matches

If an MM context cannot be found based on BBSGP info and a RA UPDATE
REQUEST is received, try to find an MM context with an P-TMSI from
which the TLLI could have been derived. This also checks, whether the
routing area matches.

This is similar to the old behaviour removed by the commits
"sgsn: Only look at TLLIs in sgsn_mm_ctx_by_tlli" and
"sgsn: Remove tlli_foreign2local", except that this will only
be done for RA UPDATE REQUESTs now.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index f71066d..b7bda49 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -105,6 +105,31 @@
 	return NULL;
 }
 
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
+					const struct gprs_ra_id *raid)
+{
+	struct sgsn_mm_ctx *ctx;
+	int tlli_type;
+
+	/* TODO: Also check the P_TMSI signature to be safe. That signature
+	 * should be different (at least with a sufficiently high probability)
+	 * after SGSN restarts and for multiple SGSN instances.
+	 */
+
+	tlli_type = gprs_tlli_type(tlli);
+	if (tlli_type != TLLI_FOREIGN && tlli_type != TLLI_LOCAL)
+		return NULL;
+
+	llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
+		if ((gprs_tmsi2tlli(ctx->p_tmsi, tlli_type) == tlli ||
+		     gprs_tmsi2tlli(ctx->p_tmsi_old, tlli_type) == tlli) &&
+		    gprs_ra_id_equals(raid, &ctx->ra))
+			return ctx;
+	}
+
+	return NULL;
+}
+
 struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t p_tmsi)
 {
 	struct sgsn_mm_ctx *ctx;