aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-08-18 17:23:01 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-24 16:16:39 +0200
commit03ca10e8635d86379c80e9eb295dd1561fa36d1f (patch)
treef78bd1d1abf42536ea4f187dc6d65d2d683a14bd
parente37487e0838a03ebc5cb06cf980278d7196bc5df (diff)
gbproxy: Patch TLLI/P-TMSI
This patch adds code to modify TLLIs and P-TMSIs. Related counters are also added. Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/src/gprs/gb_proxy.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index ef2f0d417..549d3d7ed 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -95,10 +95,15 @@ enum gbprox_peer_ctr {
GBPROX_PEER_CTR_RAID_PATCHED_BSS,
GBPROX_PEER_CTR_RAID_PATCHED_SGSN,
GBPROX_PEER_CTR_APN_PATCHED,
+ GBPROX_PEER_CTR_TLLI_PATCHED_BSS,
+ GBPROX_PEER_CTR_TLLI_PATCHED_SGSN,
+ GBPROX_PEER_CTR_PTMSI_PATCHED_BSS,
+ GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN,
GBPROX_PEER_CTR_PATCH_CRYPT_ERR,
GBPROX_PEER_CTR_PATCH_ERR,
GBPROX_PEER_CTR_ATTACH_REQS,
GBPROX_PEER_CTR_ATTACH_REJS,
+ GBPROX_PEER_CTR_TLLI_UNKNOWN,
GBPROX_PEER_CTR_TLLI_CACHE_SIZE,
};
@@ -111,10 +116,15 @@ static const struct rate_ctr_desc peer_ctr_description[] = {
{ "raid-mod.bss", "RAID patched (BSS )" },
{ "raid-mod.sgsn", "RAID patched (SGSN)" },
{ "apn-mod.sgsn", "APN patched " },
+ { "tlli-mod.bss", "TLLI patched (BSS )" },
+ { "tlli-mod.sgsn", "TLLI patched (SGSN)" },
+ { "ptmsi-mod.bss", "P-TMSI patched (BSS )" },
+ { "ptmsi-mod.sgsn","P-TMSI patched (SGSN)" },
{ "mod-crypt-err", "Patch error: encrypted " },
{ "mod-err", "Patch error: other " },
{ "attach-reqs", "Attach Request count " },
{ "attach-rejs", "Attach Reject count " },
+ { "tlli-unknown", "TLLI from SGSN unknown " },
{ "tlli-cache", "TLLI cache size " },
};
@@ -983,6 +993,67 @@ static void gbprox_patch_apn_ie(struct msgb *msg,
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
}
+static int gbprox_patch_tlli(uint8_t *tlli_enc,
+ struct gbproxy_peer *peer,
+ uint32_t new_tlli,
+ int to_bss, const char *log_text)
+{
+ uint32_t tlli_be;
+ uint32_t tlli;
+ enum gbprox_peer_ctr counter =
+ to_bss ?
+ GBPROX_PEER_CTR_TLLI_PATCHED_SGSN :
+ GBPROX_PEER_CTR_TLLI_PATCHED_BSS;
+
+ memcpy(&tlli_be, tlli_enc, sizeof(tlli_be));
+ tlli = ntohl(tlli_be);
+
+ if (tlli == new_tlli)
+ return 0;
+
+ LOGP(DGPRS, LOGL_DEBUG,
+ "Patching %ss: "
+ "Replacing %08x -> %08x\n",
+ log_text, tlli, new_tlli);
+
+ tlli_be = htonl(new_tlli);
+ memcpy(tlli_enc, &tlli_be, sizeof(tlli_be));
+
+ rate_ctr_inc(&peer->ctrg->ctr[counter]);
+
+ return 1;
+}
+
+static int gbprox_patch_ptmsi(uint8_t *ptmsi_enc,
+ struct gbproxy_peer *peer,
+ uint32_t new_ptmsi,
+ int to_bss, const char *log_text)
+{
+ uint32_t ptmsi_be;
+ uint32_t ptmsi;
+ enum gbprox_peer_ctr counter =
+ to_bss ?
+ GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN :
+ GBPROX_PEER_CTR_PTMSI_PATCHED_BSS;
+ memcpy(&ptmsi_be, ptmsi_enc + 1, sizeof(ptmsi_be));
+ ptmsi = ntohl(ptmsi_be);
+
+ if (ptmsi == new_ptmsi)
+ return 0;
+
+ LOGP(DGPRS, LOGL_DEBUG,
+ "Patching %ss: "
+ "Replacing %08x -> %08x\n",
+ log_text, ptmsi, new_ptmsi);
+
+ ptmsi_be = htonl(new_ptmsi);
+ memcpy(ptmsi_enc + 1, &ptmsi_be, sizeof(ptmsi_be));
+
+ rate_ctr_inc(&peer->ctrg->ctr[counter]);
+
+ return 1;
+}
+
static int gbprox_parse_gmm_attach_req(uint8_t *data, size_t data_len,
struct gbproxy_parse_context *parse_ctx)
{
@@ -1377,6 +1448,35 @@ static int gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
if (parse_ctx->g48_hdr && !allow_message_patching(peer, parse_ctx->g48_hdr->msg_type))
return have_patched;
+ if (parse_ctx->ptmsi_enc && tlli_info) {
+ uint32_t ptmsi;
+ if (parse_ctx->to_bss)
+ ptmsi = tlli_info->tlli.ptmsi;
+ else
+ ptmsi = tlli_info->sgsn_tlli.ptmsi;
+
+ if (ptmsi != GSM_RESERVED_TMSI) {
+ if (gbprox_patch_ptmsi(parse_ctx->ptmsi_enc, peer,
+ ptmsi, parse_ctx->to_bss, "P-TMSI"))
+ have_patched = 1;
+ } else {
+ /* TODO: invalidate old RAI if present (see below) */
+ }
+ }
+
+ if (parse_ctx->new_ptmsi_enc && tlli_info) {
+ uint32_t ptmsi;
+ if (parse_ctx->to_bss)
+ ptmsi = tlli_info->tlli.ptmsi;
+ else
+ ptmsi = tlli_info->sgsn_tlli.ptmsi;
+
+ OSMO_ASSERT(ptmsi);
+ if (gbprox_patch_ptmsi(parse_ctx->new_ptmsi_enc, peer,
+ ptmsi, parse_ctx->to_bss, "new P-TMSI"))
+ have_patched = 1;
+ }
+
if (parse_ctx->raid_enc) {
gbprox_patch_raid(parse_ctx->raid_enc, peer, parse_ctx->to_bss,
parse_ctx->llc_msg_name);
@@ -1817,6 +1917,29 @@ static void gbprox_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_le
goto patch_error;
}
+ if (parse_ctx->tlli_enc && tlli_info) {
+ uint32_t tlli = gbprox_map_tlli(parse_ctx->tlli,
+ tlli_info, parse_ctx->to_bss);
+
+ if (tlli) {
+ gbprox_patch_tlli(parse_ctx->tlli_enc, peer, tlli,
+ parse_ctx->to_bss, "TLLI");
+ parse_ctx->tlli = tlli;
+ } else if (parse_ctx->to_bss) {
+ /* Happens with unknown (not cached) TLLI coming from
+ * the SGSN */
+ /* TODO: What shall be done with the message in this case? */
+ err_ctr = GBPROX_PEER_CTR_TLLI_UNKNOWN;
+ err_info = "TLLI sent by the SGSN is unknown";
+ goto patch_error;
+ } else {
+ /* Internal error */
+ err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
+ err_info = "Replacement TLLI is 0";
+ goto patch_error;
+ }
+ }
+
if (parse_ctx->llc) {
uint8_t *llc = parse_ctx->llc;
size_t llc_len = parse_ctx->llc_len;