aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-08-06 18:55:15 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2014-08-13 10:29:09 +0200
commit89d3d343d1d15fb5f48826c73171c51b61b47efb (patch)
tree48eddc9c29f08eb65198a6b9b9478aeaaffa023b
parent58da91d5d0a43f2fcccae842c805e7c49f95e534 (diff)
gbproxy: Track TLLI even when the IMSI is not known
Currently only TLLIs for which it is known that they may be patched are put into the TLLI list. This patch changes this to add TLLIs even when the IMSI is not yet known. A enable_patching flag is added to the gbproxy_tlli_info structure to control patching. Note that this puts every active TLLI into the list where accesses are O(N) currently. Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/include/openbsc/gb_proxy.h2
-rw-r--r--openbsc/src/gprs/gb_proxy.c94
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c12
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.c12
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.ok14
5 files changed, 86 insertions, 48 deletions
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h
index 3f8155182..5a580cdb9 100644
--- a/openbsc/include/openbsc/gb_proxy.h
+++ b/openbsc/include/openbsc/gb_proxy.h
@@ -88,6 +88,8 @@ struct gbproxy_tlli_info {
time_t timestamp;
uint8_t *mi_data;
size_t mi_data_len;
+
+ int enable_patching;
};
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 98b10b972..103ecb59e 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -439,6 +439,9 @@ struct gbproxy_tlli_info *gbprox_find_tlli_by_mi(
struct gbproxy_tlli_info *tlli_info;
struct gbproxy_patch_state *state = &peer->patch_state;
+ if (!is_mi_imsi(mi_data, mi_data_len))
+ return NULL;
+
llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
if (tlli_info->mi_data_len != mi_data_len)
continue;
@@ -600,6 +603,9 @@ static struct gbproxy_tlli_info *gbprox_get_detached_tlli_info(
static void gbprox_update_tlli_info(struct gbproxy_tlli_info *tlli_info,
const uint8_t *imsi, size_t imsi_len)
{
+ if (!is_mi_imsi(imsi, imsi_len))
+ return;
+
tlli_info->mi_data_len = imsi_len;
tlli_info->mi_data =
talloc_realloc_size(tlli_info, tlli_info->mi_data, imsi_len);
@@ -607,26 +613,35 @@ static void gbprox_update_tlli_info(struct gbproxy_tlli_info *tlli_info,
memcpy(tlli_info->mi_data, imsi, imsi_len);
}
+void gbprox_reassign_tlli(struct gbproxy_tlli_info *tlli_info,
+ struct gbproxy_peer *peer, uint32_t new_tlli)
+{
+ if (new_tlli == tlli_info->tlli)
+ return;
+
+ LOGP(DGPRS, LOGL_INFO,
+ "The TLLI has been reassigned from %08x to %08x\n",
+ tlli_info->tlli, new_tlli);
+
+ /* TODO: Save old TLLI */
+ tlli_info->tlli = new_tlli;
+}
+
void gbprox_register_tlli(struct gbproxy_peer *peer, uint32_t tlli,
const uint8_t *imsi, size_t imsi_len)
{
struct gbproxy_patch_state *state = &peer->patch_state;
struct gbproxy_tlli_info *tlli_info;
- int enable_patching;
+ int enable_patching = -1;
time_t now = 0;
int tlli_already_known;
- if (!imsi || (imsi[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI)
- return;
-
- if (!peer->cfg->check_imsi)
- return;
-
/* Check, whether the IMSI matches */
- enable_patching = gbprox_check_imsi(peer, imsi, imsi_len);
-
- if (enable_patching < 0)
- return;
+ if (is_mi_imsi(imsi, imsi_len)) {
+ enable_patching = gbprox_check_imsi(peer, imsi, imsi_len);
+ if (enable_patching < 0)
+ return;
+ }
tlli_info = gbprox_find_tlli(peer, tlli);
@@ -644,32 +659,23 @@ void gbprox_register_tlli(struct gbproxy_peer *peer, uint32_t tlli,
tlli_already_known = tlli_info != NULL;
- if (!tlli_already_known && !enable_patching)
- return;
-
tlli_info = gbprox_get_detached_tlli_info(peer, tlli_info, tlli);
OSMO_ASSERT(tlli_info != NULL);
- if (enable_patching) {
- if (!tlli_already_known)
- LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n", tlli);
+ if (!tlli_already_known)
+ LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n", tlli);
- now = time(NULL);
+ now = time(NULL);
- gbprox_attach_tlli_info(peer, now, tlli_info);
- gbprox_update_tlli_info(tlli_info, imsi, imsi_len);
+ gbprox_attach_tlli_info(peer, now, tlli_info);
+ gbprox_update_tlli_info(tlli_info, imsi, imsi_len);
+ if (enable_patching >= 0)
+ tlli_info->enable_patching = enable_patching;
- gbprox_remove_stale_tllis(peer, now);
- /* Be on the safe side, currently the new tlli_info won't be
- * removed, but this not enforced explicitely */
- tlli_info = NULL;
- } else {
- LOGP(DGPRS, LOGL_INFO,
- "Removing TLLI %08x from list (patching no longer enabled)\n",
- tlli);
- talloc_free(tlli_info);
- tlli_info = NULL;
- }
+ gbprox_remove_stale_tllis(peer, now);
+ /* Be on the safe side, currently the new tlli_info won't be
+ * removed, but this not enforced explicitely */
+ tlli_info = NULL;
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
state->enabled_tllis_count;
@@ -694,11 +700,17 @@ static void gbprox_unregister_tlli(struct gbproxy_peer *peer, uint32_t tlli)
static int gbprox_check_tlli(struct gbproxy_peer *peer, uint32_t tlli)
{
+ struct gbproxy_tlli_info *tlli_info;
+
LOGP(DGPRS, LOGL_INFO, "Checking TLLI %08x, class: %d\n",
tlli, gprs_tlli_type(tlli));
- return !peer->cfg->check_imsi ||
- gbprox_find_tlli(peer, tlli) != NULL;
+ if (!peer->cfg->check_imsi)
+ return 1;
+
+ tlli_info = gbprox_find_tlli(peer, tlli);
+
+ return tlli_info != NULL && tlli_info->enable_patching;
}
/* check whether patching is enabled at this level */
@@ -1240,6 +1252,13 @@ static void gbprox_update_state(struct gbproxy_peer *peer,
struct gbproxy_parse_context *parse_ctx)
{
const char *msg_name = "BSSGP";
+ struct gbproxy_tlli_info *tlli_info = NULL;
+
+ if (!peer->cfg->check_imsi)
+ return;
+
+ if (parse_ctx->tlli_enc)
+ tlli_info = gbprox_find_tlli(peer, parse_ctx->tlli);
if (parse_ctx->llc_msg_name)
msg_name = parse_ctx->llc_msg_name;
@@ -1290,7 +1309,8 @@ static void gbprox_update_state(struct gbproxy_peer *peer,
msg_name, mi_buf);
}
- if (parse_ctx->new_ptmsi_enc && parse_ctx->to_bss && parse_ctx->imsi) {
+ if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc &&
+ parse_ctx->to_bss) {
/* A new PTMSI has been signaled in the message,
* register new TLLI */
uint32_t new_ptmsi;
@@ -1306,9 +1326,11 @@ static void gbprox_update_state(struct gbproxy_peer *peer,
LOGP(DGPRS, LOGL_INFO,
"Got new TLLI/PTMSI %08x/%08x (current is %08x)\n",
new_tlli, new_ptmsi, parse_ctx->tlli);
- gbprox_register_tlli(peer, new_ptmsi,
+ if (tlli_info)
+ gbprox_reassign_tlli(tlli_info, peer, new_tlli);
+ gbprox_register_tlli(peer, new_tlli,
parse_ctx->imsi, parse_ctx->imsi_len);
- } else if (parse_ctx->tlli && parse_ctx->imsi) {
+ } else if (parse_ctx->tlli_enc && parse_ctx->llc) {
gbprox_register_tlli(peer, parse_ctx->tlli,
parse_ctx->imsi, parse_ctx->imsi_len);
}
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index 68d5e74d0..ec73ae646 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -368,10 +368,14 @@ DEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis",
llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
time_t age = now - tlli_info->timestamp;
- snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
- gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
- tlli_info->mi_data,
- tlli_info->mi_data_len);
+ if (tlli_info->mi_data_len > 0) {
+ snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
+ gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
+ tlli_info->mi_data,
+ tlli_info->mi_data_len);
+ } else {
+ snprintf(mi_buf, sizeof(mi_buf), "(none)");
+ }
vty_out(vty, " TLLI %08x, IMSI %s, AGE %d%s",
tlli_info->tlli, mi_buf, (int)age,
VTY_NEWLINE);
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c
index 769dc675d..229d2d45f 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.c
+++ b/openbsc/tests/gbproxy/gbproxy_test.c
@@ -116,10 +116,14 @@ static int dump_peers(FILE *stream, int indent, struct gbproxy_config *cfg)
llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
char mi_buf[200];
time_t age = now - tlli_info->timestamp;
- snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
- gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
- tlli_info->mi_data,
- tlli_info->mi_data_len);
+ if (tlli_info->mi_data_len > 0) {
+ snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
+ gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
+ tlli_info->mi_data,
+ tlli_info->mi_data_len);
+ } else {
+ snprintf(mi_buf, sizeof(mi_buf), "(none)");
+ }
rc = fprintf(stream,
"%*s TLLI %08x, IMSI %s, AGE %d\n",
indent, "",
diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok
index ee67c33ef..455364883 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.ok
+++ b/openbsc/tests/gbproxy/gbproxy_test.ok
@@ -1807,8 +1807,9 @@ Peers:
RAID patched (SGSN): 3
APN patched : 3
Attach Request count : 1
- TLLI cache size : 1
- TLLI-Cache: 1
+ TLLI cache size : 2
+ TLLI-Cache: 2
+ TLLI efe2b700, IMSI (none), AGE 0
TLLI efe28117, IMSI 12131415161718, AGE 0
PROCESSING DETACH REQ from 0x01020304:1111
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 7e e1 41
@@ -1841,7 +1842,9 @@ Peers:
RAID patched (SGSN): 3
APN patched : 3
Attach Request count : 1
- TLLI-Cache: 0
+ TLLI cache size : 1
+ TLLI-Cache: 1
+ TLLI efe28117, IMSI 12131415161718, AGE 0
--- Bad cases ---
TLLI is already detached, shouldn't patch
@@ -1879,7 +1882,10 @@ Peers:
RAID patched (SGSN): 3
APN patched : 3
Attach Request count : 1
- TLLI-Cache: 0
+ TLLI cache size : 2
+ TLLI-Cache: 2
+ TLLI efe2b700, IMSI (none), AGE 0
+ TLLI efe28117, IMSI 12131415161718, AGE 0
Test TLLI info expiry
Test TLLI replacement: