aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-09-17 10:56:38 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2014-09-19 11:21:35 +0200
commit91a0e8639a74231f41d14ca7cc952079cc541755 (patch)
treef908e1752528fc985f953f25f2c9e06b774d209e /openbsc/src/gprs
parentaf952baffc73dae23d9498518ec26a30f50f07f0 (diff)
gbproxy: Separate SGSN numeric namespaces
Currently the SGSN side message's TLLI are searched without checking the originating SGSN. This leads to collisions if both SGSN use the same P-TMSI for different MS. With this patch, the SGSN NSEI is stored within the tlli_info and is used in comparisons to separate the namespaces. Note that this type of collision cannot happen with BSS numbers, since the tlli_info are already separated and stored per (BSS) peer. Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src/gprs')
-rw-r--r--openbsc/src/gprs/gb_proxy.c19
-rw-r--r--openbsc/src/gprs/gb_proxy_tlli.c27
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c32
3 files changed, 58 insertions, 20 deletions
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index ee8037565..4b46b0e2b 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -257,7 +257,7 @@ uint32_t gbproxy_make_sgsn_tlli(struct gbproxy_peer *peer,
sgsn_tlli = rand_r(&peer->cfg->sgsn_tlli_state);
sgsn_tlli = (sgsn_tlli & 0x7fffffff) | 0x78000000;
- if (gbproxy_find_tlli_by_sgsn_tlli(peer, sgsn_tlli))
+ if (gbproxy_find_tlli_by_any_sgsn_tlli(peer, sgsn_tlli))
sgsn_tlli = 0;
} while (!sgsn_tlli);
}
@@ -309,6 +309,7 @@ static void gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
while ((stored_msg = msgb_dequeue(&tlli_info->stored_msgs))) {
struct gprs_gb_parse_context tmp_parse_ctx = {0};
tmp_parse_ctx.to_bss = 0;
+ tmp_parse_ctx.peer_nsei = msgb_nsei(stored_msg);
int len_change = 0;
gprs_gb_parse_bssgp(msgb_bssgph(stored_msg),
@@ -511,13 +512,13 @@ static int gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
time_t now;
struct gbproxy_tlli_info *tlli_info = NULL;
uint32_t sgsn_nsei = cfg->nsip_sgsn_nsei;
- int send_msg_directly = 0;
if (!cfg->core_mcc && !cfg->core_mnc && !cfg->core_apn &&
!cfg->acquire_imsi && !cfg->patch_ptmsi && !cfg->route_to_sgsn2)
return 1;
parse_ctx.to_bss = 0;
+ parse_ctx.peer_nsei = msgb_nsei(msg);
/* Parse BSSGP/LLC */
rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
@@ -560,11 +561,16 @@ static int gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
}
}
- if (tlli_info && cfg->route_to_sgsn2 && gbproxy_check_tlli(peer, tlli_info)) {
- sgsn_nsei = cfg->nsip_sgsn2_nsei;
- send_msg_directly = 1;
+ if (tlli_info && cfg->route_to_sgsn2) {
+ if (cfg->acquire_imsi && tlli_info->imsi_len == 0)
+ sgsn_nsei = 0xffff;
+ else if (gbproxy_check_tlli(peer, tlli_info))
+ sgsn_nsei = cfg->nsip_sgsn2_nsei;
}
+ if (tlli_info)
+ tlli_info->sgsn_nsei = sgsn_nsei;
+
/* Handle IMSI acquisition */
if (cfg->acquire_imsi) {
rc = gbproxy_imsi_acquisition(peer, msg, sgsn_nsei, now,
@@ -578,7 +584,7 @@ static int gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
gbproxy_update_tlli_state_after(peer, tlli_info, now, &parse_ctx);
- if (send_msg_directly) {
+ if (sgsn_nsei != cfg->nsip_sgsn_nsei) {
/* Send message directly to the selected SGSN */
rc = gbprox_relay2sgsn(cfg, msg, msgb_bvci(msg), sgsn_nsei);
/* Don't let the calling code handle the transmission */
@@ -604,6 +610,7 @@ static void gbprox_process_bssgp_dl(struct gbproxy_config *cfg,
return;
parse_ctx.to_bss = 1;
+ parse_ctx.peer_nsei = msgb_nsei(msg);
rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
&parse_ctx);
diff --git a/openbsc/src/gprs/gb_proxy_tlli.c b/openbsc/src/gprs/gb_proxy_tlli.c
index c4140f7e8..8aadd2f44 100644
--- a/openbsc/src/gprs/gb_proxy_tlli.c
+++ b/openbsc/src/gprs/gb_proxy_tlli.c
@@ -60,16 +60,33 @@ struct gbproxy_tlli_info *gbproxy_find_tlli_by_ptmsi(
return NULL;
}
-struct gbproxy_tlli_info *gbproxy_find_tlli_by_sgsn_tlli(
+struct gbproxy_tlli_info *gbproxy_find_tlli_by_any_sgsn_tlli(
struct gbproxy_peer *peer,
uint32_t tlli)
{
struct gbproxy_tlli_info *tlli_info;
struct gbproxy_patch_state *state = &peer->patch_state;
+ /* Don't care about the NSEI */
llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
if (tlli_info->sgsn_tlli.current == tlli ||
- tlli_info->sgsn_tlli.assigned == tlli)
+ tlli_info->sgsn_tlli.assigned == tlli)
+ return tlli_info;
+
+ return NULL;
+}
+
+struct gbproxy_tlli_info *gbproxy_find_tlli_by_sgsn_tlli(
+ struct gbproxy_peer *peer,
+ uint32_t tlli, uint32_t sgsn_nsei)
+{
+ struct gbproxy_tlli_info *tlli_info;
+ struct gbproxy_patch_state *state = &peer->patch_state;
+
+ llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
+ if ((tlli_info->sgsn_tlli.current == tlli ||
+ tlli_info->sgsn_tlli.assigned == tlli) &&
+ tlli_info->sgsn_nsei == sgsn_nsei)
return tlli_info;
return NULL;
@@ -409,7 +426,8 @@ static void gbproxy_remove_matching_tllis(struct gbproxy_peer *peer,
continue;
if (!gbproxy_tlli_match(&tlli_info->tlli, &info->tlli) &&
- !gbproxy_tlli_match(&tlli_info->sgsn_tlli, &info->sgsn_tlli))
+ (tlli_info->sgsn_nsei != info->sgsn_nsei ||
+ !gbproxy_tlli_match(&tlli_info->sgsn_tlli, &info->sgsn_tlli)))
continue;
LOGP(DGPRS, LOGL_INFO,
@@ -508,7 +526,8 @@ struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
struct gbproxy_tlli_info *tlli_info = NULL;
if (parse_ctx->tlli_enc)
- tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
+ tlli_info = gbproxy_find_tlli_by_sgsn_tlli(
+ peer, parse_ctx->tlli, parse_ctx->peer_nsei);
if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && tlli_info) {
/* A new P-TMSI has been signalled in the message,
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index 22592a162..da615630e 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -479,6 +479,10 @@ DEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis",
if (stored_msgs)
vty_out(vty, ", STORED %d", stored_msgs);
+ if (g_cfg->route_to_sgsn2)
+ vty_out(vty, ", SGSN NSEI %d",
+ tlli_info->sgsn_nsei);
+
if (tlli_info->is_deregistered)
vty_out(vty, ", DE-REGISTERED");
@@ -583,15 +587,15 @@ DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
"Delete a GBProxy TLLI entry by NSEI and identification\nNSEI number\n"
DEFUN(delete_gb_tlli_by_id, delete_gb_tlli_by_id_cmd,
- "delete-gbproxy-tlli <0-65534> (tlli|imsi) IDENT",
+ "delete-gbproxy-tlli <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
GBPROXY_DELETE_TLLI_STR
"Delete entries with a matching TLLI (hex)\n"
"Delete entries with a matching IMSI\n"
"Identification to match\n")
{
const uint16_t nsei = atoi(argv[0]);
- enum {MATCH_TLLI = 't', MATCH_IMSI = 'i'} match;
- uint32_t tlli = 0;
+ enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
+ uint32_t ident = 0;
const char *imsi = NULL;
struct gbproxy_peer *peer = 0;
struct gbproxy_tlli_info *tlli_info, *nxt;
@@ -601,10 +605,11 @@ DEFUN(delete_gb_tlli_by_id, delete_gb_tlli_by_id_cmd,
match = argv[1][0];
- if (match == MATCH_TLLI)
- tlli = strtoll(argv[2], NULL, 16);
- else
- imsi = argv[2];
+ switch (match) {
+ case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
+ case MATCH_IMSI: imsi = argv[2]; break;
+ case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
+ };
peer = gbproxy_peer_by_nsei(g_cfg, nsei);
if (!peer) {
@@ -616,10 +621,16 @@ DEFUN(delete_gb_tlli_by_id, delete_gb_tlli_by_id_cmd,
state = &peer->patch_state;
llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list) {
- if (match == MATCH_TLLI) {
- if (tlli_info->tlli.current != tlli)
+ switch (match) {
+ case MATCH_TLLI:
+ if (tlli_info->tlli.current != ident)
+ continue;
+ break;
+ case MATCH_SGSN:
+ if (tlli_info->sgsn_nsei != ident)
continue;
- } else {
+ break;
+ case MATCH_IMSI:
mi_buf[0] = '\0';
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
tlli_info->imsi,
@@ -627,6 +638,7 @@ DEFUN(delete_gb_tlli_by_id, delete_gb_tlli_by_id_cmd,
if (strcmp(mi_buf, imsi) != 0)
continue;
+ break;
}
vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli.current,