gbproxy: Patch BSSGP P-TMSI in PAGING PS messages

Currently the P-TMSI IE in PAGING_PS is not patched.

This commit adds code to patch BSSGP P-TMSI IE in
gbproxy_patch_bssgp independently from the P-TMSI patching at the LLC
layer. It also extends gbproxy_update_link_state_dl to use the IMSI
to find the link_info if the TLLI is not present in the message.

Note that the spec (GSM 08.18, 7.2) requires to use of the P-TMSI
instead of the IMSI to select the MS if that IE is available.
Nevertheless as long as the IMSI is always present in downlink BSSGP
messages and as long as the optional P-TMSI refers to the same MS
(which is the case currently), this is not an issue.

Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2014-09-30 13:49:43 +02:00
parent 91e9f555b6
commit c37ef6cd0e
6 changed files with 133 additions and 9 deletions

View File

@ -29,7 +29,7 @@ struct gprs_gb_parse_context {
uint8_t *raid_enc;
uint8_t *old_raid_enc;
uint8_t *bssgp_raid_enc;
uint8_t *bssgp_ptimsi;
uint8_t *bssgp_ptmsi_enc;
/* General info */
const char *llc_msg_name;

View File

@ -327,6 +327,19 @@ void gbproxy_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
}
}
if (parse_ctx->bssgp_ptmsi_enc && peer->cfg->patch_ptmsi) {
uint32_t ptmsi;
if (parse_ctx->to_bss)
ptmsi = link_info->tlli.ptmsi;
else
ptmsi = link_info->sgsn_tlli.ptmsi;
if (ptmsi != GSM_RESERVED_TMSI)
gbproxy_patch_ptmsi(
parse_ctx->bssgp_ptmsi_enc, peer,
ptmsi, parse_ctx->to_bss, "BSSGP P-TMSI");
}
if (parse_ctx->llc) {
uint8_t *llc = parse_ctx->llc;
size_t llc_len = parse_ctx->llc_len;

View File

@ -542,6 +542,30 @@ struct gbproxy_link_info *gbproxy_update_link_state_ul(
return link_info;
}
static struct gbproxy_link_info *gbproxy_get_link_info_dl(
struct gbproxy_peer *peer,
struct gprs_gb_parse_context *parse_ctx)
{
struct gbproxy_link_info *link_info = NULL;
/* Which key to use depends on its availability only, if that fails, do
* not retry it with another key (e.g. IMSI). */
if (parse_ctx->tlli_enc)
link_info = gbproxy_link_info_by_sgsn_tlli(peer, parse_ctx->tlli,
parse_ctx->peer_nsei);
/* TODO: Get link_info by (SGSN) P-TMSI if that is available (see
* GSM 08.18, 7.2) instead of using the IMSI as key. */
else if (parse_ctx->imsi)
link_info = gbproxy_link_info_by_imsi(
peer, parse_ctx->imsi, parse_ctx->imsi_len);
if (link_info)
link_info->is_deregistered = 0;
return link_info;
}
struct gbproxy_link_info *gbproxy_update_link_state_dl(
struct gbproxy_peer *peer,
time_t now,
@ -549,9 +573,7 @@ struct gbproxy_link_info *gbproxy_update_link_state_dl(
{
struct gbproxy_link_info *link_info = NULL;
if (parse_ctx->tlli_enc)
link_info = gbproxy_link_info_by_sgsn_tlli(
peer, parse_ctx->tlli, parse_ctx->peer_nsei);
link_info = gbproxy_get_link_info_dl(peer, parse_ctx);
if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && link_info) {
/* A new P-TMSI has been signalled in the message,

View File

@ -596,7 +596,7 @@ int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
}
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);
parse_ctx->bssgp_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);
@ -633,6 +633,7 @@ void gprs_gb_log_parse_context(int log_level,
if (!parse_ctx->tlli_enc &&
!parse_ctx->ptmsi_enc &&
!parse_ctx->new_ptmsi_enc &&
!parse_ctx->bssgp_ptmsi_enc &&
!parse_ctx->imsi)
return;
@ -681,6 +682,13 @@ void gprs_gb_log_parse_context(int log_level,
sep = ",";
}
if (parse_ctx->bssgp_ptmsi_enc) {
uint32_t ptmsi = GSM_RESERVED_TMSI;
gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi);
LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi);
sep = ",";
}
if (parse_ctx->ptmsi_enc) {
uint32_t ptmsi = GSM_RESERVED_TMSI;
gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi);

View File

@ -721,6 +721,53 @@ static void send_bssgp_llc_discarded(struct gprs_ns_inst *nsi,
send_ns_unitdata(nsi, "LLC_DISCARDED", src_addr, 0, msg, sizeof(msg));
}
static void send_bssgp_paging(struct gprs_ns_inst *nsi,
struct sockaddr_in *src_addr,
const uint8_t *imsi, size_t imsi_size,
struct gprs_ra_id *raid, uint32_t ptmsi)
{
/* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
unsigned char msg[100] = {
0x06,
};
const unsigned char drx_ie[] = {0x0a, 0x82, 0x07, 0x04};
const unsigned char qos_ie[] = {0x18, 0x83, 0x00, 0x00, 0x00};
size_t bssgp_msg_size = 1;
if (imsi) {
OSMO_ASSERT(imsi_size <= 127);
msg[bssgp_msg_size] = BSSGP_IE_IMSI;
msg[bssgp_msg_size + 1] = 0x80 | imsi_size;
memcpy(msg + bssgp_msg_size + 2, imsi, imsi_size);
bssgp_msg_size += 2 + imsi_size;
}
memcpy(msg + bssgp_msg_size, drx_ie, sizeof(drx_ie));
bssgp_msg_size += sizeof(drx_ie);
if (raid) {
msg[bssgp_msg_size] = BSSGP_IE_ROUTEING_AREA;
msg[bssgp_msg_size+1] = 0x86;
gsm48_construct_ra(msg + bssgp_msg_size + 2, raid);
bssgp_msg_size += 8;
}
memcpy(msg + bssgp_msg_size, qos_ie, sizeof(qos_ie));
bssgp_msg_size += sizeof(qos_ie);
if (ptmsi != GSM_RESERVED_TMSI) {
const uint32_t ptmsi_be = htonl(ptmsi);
msg[bssgp_msg_size] = BSSGP_IE_TMSI;
msg[bssgp_msg_size+1] = 0x84;
memcpy(msg + bssgp_msg_size + 2, &ptmsi_be, 4);
bssgp_msg_size += 6;
}
send_ns_unitdata(nsi, "PAGING_PS", src_addr, 0, msg, bssgp_msg_size);
}
static void send_bssgp_flow_control_bvc(struct gprs_ns_inst *nsi,
struct sockaddr_in *src_addr,
uint16_t bvci, uint8_t tag)
@ -2127,6 +2174,7 @@ static void test_gbproxy_ptmsi_patching()
struct gbproxy_peer *peer;
unsigned bss_nu = 0;
unsigned sgsn_nu = 0;
int old_ctr;
OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
OSMO_ASSERT(local_sgsn_tlli2 == gprs_tmsi2tlli(sgsn_ptmsi2, TLLI_LOCAL));
@ -2366,6 +2414,15 @@ static void test_gbproxy_ptmsi_patching()
dump_peers(stdout, 0, 0, &gbcfg);
old_ctr = peer->ctrg->ctr[GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN].current;
send_bssgp_paging(nsi, &sgsn_peer, imsi, sizeof(imsi), &rai_bss, sgsn_ptmsi3);
dump_peers(stdout, 0, 0, &gbcfg);
OSMO_ASSERT(old_ctr + 1 ==
peer->ctrg->ctr[GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN].current);
/* Bad case: Invalid BVCI */
send_bssgp_llc_discarded(nsi, &bss_peer[0], 0xeee1,
local_bss_tlli3, 1, 12);

View File

@ -2756,6 +2756,30 @@ Peers:
TLLI cache size : 1
TLLI-Cache: 1
TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0
PROCESSING PAGING_PS from 0x05060708:32000
00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 e0 54 32 10
CALLBACK, event 0, msg length 34, bvci 0x0000
00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 e0 54 32 10
NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 34 (gprs_ns_sendmsg)
MESSAGE to BSS at 0x01020304:1111, msg length 38
00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 ea d4 77 5a
result (PAGING_PS) = 38
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 13
RAID patched (SGSN): 5
APN patched : 1
TLLI patched (BSS ): 11
TLLI patched (SGSN): 9
P-TMSI patched (SGSN): 4
Attach Request count : 1
TLLI cache size : 1
TLLI-Cache: 1
TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0
PROCESSING LLC_DISCARDED from 0x01020304:1111
00 00 00 00 2c 1f 84 ea d4 77 5a 0f 81 01 04 82 ee e1 25 83 00 00 0c
@ -2838,12 +2862,12 @@ result (DETACH REQ) = 48
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 14
RAID patched (SGSN): 5
RAID patched (SGSN): 6
APN patched : 1
TLLI patched (BSS ): 13
TLLI patched (SGSN): 10
P-TMSI patched (BSS ): 1
P-TMSI patched (SGSN): 3
P-TMSI patched (SGSN): 4
Attach Request count : 1
TLLI from SGSN unknown : 2
TLLI cache size : 1
@ -2864,12 +2888,12 @@ result (DETACH ACC) = 71
Peers:
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
RAID patched (BSS ): 14
RAID patched (SGSN): 5
RAID patched (SGSN): 6
APN patched : 1
TLLI patched (BSS ): 13
TLLI patched (SGSN): 11
P-TMSI patched (BSS ): 1
P-TMSI patched (SGSN): 3
P-TMSI patched (SGSN): 4
Attach Request count : 1
TLLI from SGSN unknown : 2
TLLI-Cache: 0