aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gb_proxy.c
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-06-27 18:10:53 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-07-22 17:11:57 +0200
commit2e2650f8f33201b1794f656cc8e64657eebee522 (patch)
treeb5b11218dd23b61e4b26e04823cf624c716c0409 /openbsc/src/gprs/gb_proxy.c
parent35cc03f97d7d957bfecd540549a2d0cc809c8684 (diff)
gprs: Parse PTMSI and update TLLI accordingly
This commit adds code to parse the PTMSI in network originated messages - Attach Accept, - Routing Area Update Accept, and - P-TMSI Reallocation Command (see below) to keep track of the TLLI identifying the LLC connection. The P_TMSI Realloc Command specific code is not being tested yet, so a corresponding notice is logged when such a message will be received. NOTE: The gbproxy will lose the TLLI when the MS doesn't receive/use the message (normally the SGSN remembers the old TLLI for some time to avoid this kind of problem). If this happens the MS will probably restart the procedure and the network will have to answer again eventually using one of the above messages which will re-associate the IMSI with the TLLI before the MS can send a PDP Context Request message. Ticket: OW#1192 Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src/gprs/gb_proxy.c')
-rw-r--r--openbsc/src/gprs/gb_proxy.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 5fcd25a5b..b41bedb18 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -519,6 +519,23 @@ fail:
return -1;
}
+static int parse_mi_tmsi(uint8_t *value, size_t value_len, uint32_t *tmsi)
+{
+ uint32_t tmsi_be;
+
+ if (value_len != GSM48_TMSI_LEN)
+ return 0;
+
+ if ((value[0] & 0x0f) != GSM_MI_TYPE_TMSI)
+ return 0;
+
+ memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
+
+ *tmsi = ntohl(tmsi_be);
+
+ return 1;
+}
+
struct gbprox_parse_context {
/* Pointer to protocol specific parts */
struct gsm48_hdr *g48_hdr;
@@ -991,6 +1008,7 @@ static int gbprox_patch_gmm_attach_ack(struct msgb *msg,
struct gbprox_parse_context *parse_ctx)
{
uint8_t *value;
+ size_t value_len;
/* Skip Attach result */
/* Skip Force to standby */
@@ -1004,6 +1022,17 @@ static int gbprox_patch_gmm_attach_ack(struct msgb *msg,
gbprox_patch_raid(value, peer, parse_ctx->to_bss, "LLC/ATTACH_ACK");
+ /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
+ tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
+
+ /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
+ tv_fixed_match(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
+
+ /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
+ if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
+ &value, &value_len) > 0)
+ parse_mi_tmsi(value, value_len, &parse_ctx->new_ptmsi);
+
return 1;
}
@@ -1032,6 +1061,7 @@ static int gbprox_patch_gmm_ra_upd_ack(struct msgb *msg,
struct gbprox_parse_context *parse_ctx)
{
uint8_t *value;
+ size_t value_len;
/* Skip Force to standby */
/* Skip Update result */
@@ -1043,6 +1073,13 @@ static int gbprox_patch_gmm_ra_upd_ack(struct msgb *msg,
gbprox_patch_raid(value, peer, parse_ctx->to_bss, "LLC/RA_UPD_ACK");
+ /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
+ tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
+
+ /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
+ if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
+ &value, &value_len) > 0)
+ parse_mi_tmsi(value, value_len, &parse_ctx->new_ptmsi);
return 1;
}
@@ -1056,8 +1093,12 @@ static int gbprox_patch_gmm_ptmsi_reall_cmd(struct msgb *msg,
uint8_t *value;
size_t value_len;
- /* Skip Allocated P-TMSI */
- if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 || value_len != 5)
+ LOGP(DLLC, LOGL_NOTICE,
+ "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
+
+ /* Allocated P-TMSI */
+ if (lv_shift(&data, &data_len, &value, &value_len) > 0 &&
+ parse_mi_tmsi(value, value_len, &parse_ctx->new_ptmsi) < 0)
/* invalid */
return 0;
@@ -1272,6 +1313,17 @@ static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
rc = gbprox_patch_dtap(msg, data, data_len, peer, &len_change, parse_ctx);
+ if (parse_ctx->new_ptmsi &&
+ (parse_ctx->new_ptmsi | 0xc000) != (tlli | 0xc000) &&
+ gbcfg.core_apn && parse_ctx->to_bss && parse_ctx->imsi) {
+ /* A new TLLI (PTMSI) has been signaled in the message */
+ LOGP(DGPRS, LOGL_INFO,
+ "Got new TLLI/PTMSI %08x (current is %08x)\n",
+ parse_ctx->new_ptmsi, tlli);
+ gbprox_register_tlli(peer, parse_ctx->new_ptmsi,
+ parse_ctx->imsi, parse_ctx->imsi_len);
+ }
+
if (rc > 0) {
llc_len += len_change;
ghp.crc_length += len_change;