ms: Support new and old TLLIs

According to the specification (GSM 04.08/24.008, 4.7.1.5) after a
new P-TMSI has been assigned, the old P-TMSI must be kept basically
until it has been used by both sides. Since the TLLI will be derived
from the P-TMSI, the old TLLI must also be kept until the new TLLI
has been used by both MS and SGSN.

This commit modifies the TLLI handling of GprsMs accordingly.
set_tlli() is only used with TLLIs derived from MS messages,
confirm_tlli() is used with TLLIs derived from messages received from
the SGSN. tlli() returns the value set by the MS. check_tlli()
matches each of the TLLI used by either MS or SGSN as well as the old
TLLI until it has been confirmed.

Sponsored-by: On-Waves ehf
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index db271a5..1c35667 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -118,6 +118,7 @@
 	struct bssgp_ud_hdr *budh;
 
 	uint32_t tlli;
+	uint32_t tlli_old = 0;
 	uint8_t *data;
 	uint16_t len;
 	char imsi[16] = "000";
@@ -163,9 +164,22 @@
 		LOGP(DBSSGP, LOGL_NOTICE, "BSSGP missing mandatory "
 			"PDU_LIFETIME IE\n");
 
+	/* get optional TLLI old */
+	if (TLVP_PRESENT(tp, BSSGP_IE_TLLI))
+	{
+		uint8_t tlli_len = TLVP_LEN(tp, BSSGP_IE_PDU_LIFETIME);
+		uint16_t *e_tlli_old = (uint16_t *) TLVP_VAL(tp, BSSGP_IE_TLLI);
+		if (tlli_len == 2)
+			tlli_old = ntohs(*e_tlli_old);
+		else
+			LOGP(DBSSGP, LOGL_NOTICE, "BSSGP invalid length of "
+				"TLLI (old) IE\n");
+	}
+
 	LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len);
 
-	return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len);
+	return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, tlli_old, imsi,
+			ms_class, delay_csec, data, len);
 }
 
 int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp)