gbproxy: Parse additional IMSI/PTMSI/TLLI fields

This adds parsing support for the following messages:
  - Attach Request: IMSI/PTMSI
  - Identity Response: IMSI/PTMSI
  - BSSGP: Optional TLLI IE
  - BSSGP/PAGING_PS: PTMSI

A new new_ptmsi_enc field is added for newly assigned PTMSI in
SGSN->BSS messages (instead of ptmsi_enc). The ptmsi_enc field is now
used for informational PTMSI IE in messages.

Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2014-08-06 15:16:45 +02:00
parent 2db2512f4d
commit 690768a171
3 changed files with 121 additions and 14 deletions

View File

@ -359,6 +359,17 @@ static int is_mi_tmsi(uint8_t *value, size_t value_len)
return 1;
}
static int is_mi_imsi(uint8_t *value, size_t value_len)
{
if (value_len == 0)
return 0;
if (!value || (value[0] & 0x0f) != GSM_MI_TYPE_IMSI)
return 0;
return 1;
}
static int parse_mi_tmsi(uint8_t *value, size_t value_len, uint32_t *tmsi)
{
uint32_t tmsi_be;
@ -392,6 +403,7 @@ struct gbproxy_parse_context {
uint8_t *apn_ie;
size_t apn_ie_len;
uint8_t *ptmsi_enc;
uint8_t *new_ptmsi_enc;
uint8_t *raid_enc;
uint8_t *bssgp_raid_enc;
uint8_t *bssgp_ptimsi;
@ -847,11 +859,18 @@ static int gbprox_parse_gmm_attach_req(uint8_t *data, size_t data_len,
/* Skip DRX parameter */
v_fixed_shift(&data, &data_len, 3, NULL);
/* Skip Mobile identity */
if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
/* Get Mobile identity */
if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
value_len < 5 || value_len > 8)
/* invalid */
return 0;;
return 0;
if (is_mi_tmsi(value, value_len)) {
parse_ctx->ptmsi_enc = value;
} else if (is_mi_imsi(value, value_len)) {
parse_ctx->imsi = value;
parse_ctx->imsi_len = value_len;
}
if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
return 0;
@ -891,7 +910,7 @@ static int gbprox_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
&value, &value_len) > 0 &&
is_mi_tmsi(value, value_len))
parse_ctx->ptmsi_enc = value;
parse_ctx->new_ptmsi_enc = value;
return 1;
}
@ -939,7 +958,7 @@ static int gbprox_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
&value, &value_len) > 0 &&
is_mi_tmsi(value, value_len))
parse_ctx->ptmsi_enc = value;
parse_ctx->new_ptmsi_enc = value;
return 1;
}
@ -958,7 +977,7 @@ static int gbprox_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
/* Allocated P-TMSI */
if (lv_shift(&data, &data_len, &value, &value_len) > 0 &&
is_mi_tmsi(value, value_len))
parse_ctx->ptmsi_enc = value;
parse_ctx->new_ptmsi_enc = value;
if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
return 0;
@ -968,6 +987,30 @@ static int gbprox_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
return 1;
}
static int gbprox_parse_gmm_id_resp(uint8_t *data, size_t data_len,
struct gbproxy_parse_context *parse_ctx)
{
uint8_t *value;
size_t value_len;
parse_ctx->llc_msg_name = "ID_RESP";
/* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
value_len < 1 || value_len > 9)
/* invalid */
return 0;
if (is_mi_tmsi(value, value_len)) {
parse_ctx->ptmsi_enc = value;
} else if (is_mi_imsi(value, value_len)) {
parse_ctx->imsi = value;
parse_ctx->imsi_len = value_len;
}
return 1;
}
static int gbprox_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
struct gbproxy_parse_context *parse_ctx)
{
@ -1067,6 +1110,10 @@ static int gbprox_parse_dtap(uint8_t *data, size_t data_len,
case GSM48_MT_GSM_ACT_PDP_REQ:
return gbprox_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
case GSM48_MT_GMM_ID_RESP:
return gbprox_parse_gmm_id_resp(data, data_len, parse_ctx);
break;
case GSM48_MT_GMM_DETACH_REQ:
/* TODO: Check power off if !to_bss, if yes invalidate */
parse_ctx->llc_msg_name = "DETACH_REQ";
@ -1216,9 +1263,17 @@ static void gbprox_update_state(struct gbproxy_peer *peer,
}
if (parse_ctx->ptmsi_enc) {
uint32_t ptmsi = GSM_RESERVED_TMSI;
int ok;
ok = parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN, &ptmsi);
LOGP(DGPRS, LOGL_DEBUG, "%s: Got PTMSI %08x%s\n",
msg_name, ptmsi, ok ? "" : " (parse error)");
}
if (parse_ctx->new_ptmsi_enc) {
uint32_t new_ptmsi = GSM_RESERVED_TMSI;
int ok;
ok = parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
ok = parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
&new_ptmsi);
LOGP(DGPRS, LOGL_DEBUG, "%s: Got new PTMSI %08x%s\n",
msg_name, new_ptmsi, ok ? "" : " (parse error)");
@ -1233,10 +1288,10 @@ static void gbprox_update_state(struct gbproxy_peer *peer,
msg_name, mi_buf);
}
if (parse_ctx->ptmsi_enc && parse_ctx->to_bss && parse_ctx->imsi) {
if (parse_ctx->new_ptmsi_enc && parse_ctx->to_bss && parse_ctx->imsi) {
/* A new TLLI (PTMSI) has been signaled in the message */
uint32_t new_ptmsi;
if (!parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
if (!parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
&new_ptmsi)) {
LOGP(DGPRS, LOGL_ERROR,
"Failed to parse new TLLI/PTMSI (current is %08x)\n",
@ -1316,6 +1371,12 @@ static int gbprox_parse_bssgp_message(uint8_t *bssgp, size_t bssgp_len,
parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
}
if (TLVP_PRESENT(tp, BSSGP_IE_TLLI))
parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
parse_ctx->ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);

View File

@ -146,6 +146,22 @@ static const unsigned char bssgp_attach_req[75] = {
0x16, 0x6d, 0x01
};
/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Identity Request */
static const unsigned char bssgp_identity_req[] = {
0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
0x16, 0x82, 0x02, 0x58, 0x0e, 0x89, 0x41, 0xc0,
0x01, 0x08, 0x15, 0x01, 0xff, 0x6c, 0xba
};
/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Identity Response */
static const unsigned char bssgp_identity_resp[] = {
0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x11, 0x01,
0xc0, 0x0d, 0x08, 0x16, 0x08, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0xb7, 0x1b, 0x9a
};
/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */
static const unsigned char bssgp_attach_acc[88] = {
0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
@ -984,6 +1000,12 @@ static void test_gbproxy_ra_patching()
send_ns_unitdata(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
bssgp_attach_req, sizeof(bssgp_attach_req));
send_ns_unitdata(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
bssgp_identity_req, sizeof(bssgp_identity_req));
send_ns_unitdata(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
bssgp_identity_resp, sizeof(bssgp_identity_resp));
send_ns_unitdata(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
bssgp_attach_acc, sizeof(bssgp_attach_acc));

View File

@ -1639,6 +1639,30 @@ MESSAGE to SGSN at 0x05060708:32000, msg length 79
result (ATTACH REQUEST) = 79
PROCESSING IDENT REQUEST from 0x05060708:32000
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba
CALLBACK, event 0, msg length 23, bvci 0x1002
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
MESSAGE to BSS at 0x01020304:1111, msg length 27
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba
result (IDENT REQUEST) = 27
PROCESSING IDENT RESPONSE from 0x01020304:1111
00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 11 01 c0 0d 08 16 08 11 12 13 14 15 16 17 18 b7 1b 9a
CALLBACK, event 0, msg length 40, bvci 0x1002
00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 11 01 c0 0d 08 16 08 11 12 13 14 15 16 17 18 b7 1b 9a
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
MESSAGE to SGSN at 0x05060708:32000, msg length 44
00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 11 01 c0 0d 08 16 08 11 12 13 14 15 16 17 18 b7 1b 9a
result (IDENT RESPONSE) = 44
PROCESSING ATTACH ACCEPT from 0x05060708:32000
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 42 67 9a
@ -1701,7 +1725,7 @@ result (ACT PDP CTX REQ (REMOVE APN)) = 75
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 7
RAID patched (BSS ): 8
RAID patched (SGSN): 2
APN patched : 3
Attach Request count : 1
@ -1734,7 +1758,7 @@ result (DETACH ACC) = 71
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 8
RAID patched (BSS ): 9
RAID patched (SGSN): 2
APN patched : 3
Attach Request count : 1
@ -1779,7 +1803,7 @@ result (ACT PDP CTX REQ (REMOVE APN)) = 80
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 11
RAID patched (BSS ): 12
RAID patched (SGSN): 3
APN patched : 3
Attach Request count : 1
@ -1813,7 +1837,7 @@ result (DETACH ACC) = 71
Gbproxy global:
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 12
RAID patched (BSS ): 13
RAID patched (SGSN): 3
APN patched : 3
Attach Request count : 1
@ -1851,7 +1875,7 @@ Gbproxy global:
Patch error: no peer : 1
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 13
RAID patched (BSS ): 14
RAID patched (SGSN): 3
APN patched : 3
Attach Request count : 1