aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-08-12 16:30:30 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-24 16:16:39 +0200
commit9057bc3c727e97cd7ff2534bffbd9ba4dcd8d4ea (patch)
treed63a0a24749b5961285515b44c4641b8a13f10ba
parentc53f2a6961780153fbf97910609c827a0e9300c3 (diff)
gbproxy: Track SGSN and BSS TLLI/PTMSI separately
This patch separates BSS side from SGSN side TLLI/PTMSI tracking. When TLLI/PTMSI patching is not enabled, the corresponding states shall be identical. The TLLI/PTMSI state has been moved into the struct gbproxy_tlli_state and is used twice in gbproxy_tlli_info. Since the state handling for uplink and downlink messages is diverging, gbprox_update_state() is replaced by two functions gbprox_update_state_dl/gbprox_update_state_ul and gbprox_process_bssgp_message() is replaced by gbprox_process_bssgp_dl/gbprox_process_bssgp_ul. Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/include/openbsc/gb_proxy.h21
-rw-r--r--openbsc/src/gprs/gb_proxy.c296
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c7
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.c96
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.ok6
5 files changed, 327 insertions, 99 deletions
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h
index adc955c8a..468228043 100644
--- a/openbsc/include/openbsc/gb_proxy.h
+++ b/openbsc/include/openbsc/gb_proxy.h
@@ -44,6 +44,7 @@ struct gbproxy_config {
enum gbproxy_patch_mode patch_mode;
int tlli_max_age;
int tlli_max_len;
+ int patch_ptmsi;
/* IMSI checking/matching */
int check_imsi;
@@ -81,17 +82,26 @@ struct gbproxy_peer {
struct gbproxy_patch_state patch_state;
};
+struct gbproxy_tlli_state {
+ uint32_t current;
+ uint32_t assigned;
+ int bss_validated;
+ int net_validated;
+
+ uint32_t ptmsi;
+};
+
struct gbproxy_tlli_info {
struct llist_head list;
- uint32_t tlli;
- uint32_t assigned_tlli;
- int bss_validated;
- int net_validated;
+ struct gbproxy_tlli_state tlli;
+ struct gbproxy_tlli_state sgsn_tlli;
+
time_t timestamp;
uint8_t *mi_data;
size_t mi_data_len;
+
int enable_patching;
};
@@ -132,6 +142,9 @@ struct gbproxy_tlli_info *gbprox_find_tlli(struct gbproxy_peer *peer,
struct gbproxy_tlli_info *gbprox_find_tlli_by_mi(struct gbproxy_peer *peer,
const uint8_t *mi_data,
size_t mi_data_len);
+struct gbproxy_tlli_info *gbprox_find_tlli_by_sgsn_tlli(
+ struct gbproxy_peer *peer,
+ uint32_t tlli);
struct gbproxy_tlli_info *gbprox_register_tlli(
struct gbproxy_peer *peer, uint32_t tlli,
const uint8_t *imsi, size_t imsi_len, time_t now);
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 26f4c1755..0c898cc9d 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -427,7 +427,23 @@ struct gbproxy_tlli_info *gbprox_find_tlli(struct gbproxy_peer *peer,
struct gbproxy_patch_state *state = &peer->patch_state;
llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
- if (tlli_info->tlli == tlli || tlli_info->assigned_tlli == tlli)
+ if (tlli_info->tlli.current == tlli ||
+ tlli_info->tlli.assigned == tlli)
+ return tlli_info;
+
+ return NULL;
+}
+
+struct gbproxy_tlli_info *gbprox_find_tlli_by_sgsn_tlli(
+ struct gbproxy_peer *peer,
+ uint32_t tlli)
+{
+ 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)
return tlli_info;
return NULL;
@@ -583,7 +599,7 @@ int gbprox_remove_stale_tllis(struct gbproxy_peer *peer, time_t now)
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list "
"(stale, length %d, max_len exceeded)\n",
- tlli_info->tlli, state->enabled_tllis_count);
+ tlli_info->tlli.current, state->enabled_tllis_count);
gbprox_delete_tlli(peer, tlli_info);
deleted_count += 1;
@@ -605,7 +621,7 @@ int gbprox_remove_stale_tllis(struct gbproxy_peer *peer, time_t now)
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list "
"(stale, age %d, max_age exceeded)\n",
- tlli_info->tlli, (int)age);
+ tlli_info->tlli.current, (int)age);
gbprox_delete_tlli(peer, tlli_info);
deleted_count += 1;
@@ -622,8 +638,9 @@ static struct gbproxy_tlli_info *gbprox_get_detached_tlli_info(
struct gbproxy_patch_state *state = &peer->patch_state;
if (!tlli_info) {
+ /* move this into an tlli_alloc function */
tlli_info = talloc_zero(peer, struct gbproxy_tlli_info);
- tlli_info->tlli = tlli;
+ tlli_info->tlli.current = tlli;
} else {
llist_del(&tlli_info->list);
OSMO_ASSERT(state->enabled_tllis_count > 0);
@@ -649,57 +666,58 @@ 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,
+void gbprox_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
struct gbproxy_peer *peer, uint32_t new_tlli)
{
- if (new_tlli == tlli_info->tlli)
+ if (new_tlli == tlli_state->current)
return;
LOGP(DGPRS, LOGL_INFO,
"The TLLI has been reassigned from %08x to %08x\n",
- tlli_info->tlli, new_tlli);
+ tlli_state->current, new_tlli);
/* Remember assigned TLLI */
- tlli_info->assigned_tlli = new_tlli;
- tlli_info->bss_validated = 0;
- tlli_info->net_validated = 0;
+ tlli_state->assigned = new_tlli;
+ tlli_state->bss_validated = 0;
+ tlli_state->net_validated = 0;
}
-static void gbprox_validate_tlli(struct gbproxy_tlli_info *tlli_info,
+static void gbprox_validate_tlli(struct gbproxy_tlli_state *tlli_state,
uint32_t tlli, int to_bss)
{
LOGP(DGPRS, LOGL_DEBUG,
- "%s({tlli = %08x, assigned_tlli = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
- __func__, tlli_info->tlli, tlli_info->assigned_tlli,
- tlli_info->net_validated, tlli_info->bss_validated, tlli);
+ "%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
+ __func__, tlli_state->current, tlli_state->assigned,
+ tlli_state->net_validated, tlli_state->bss_validated, tlli);
- if (!tlli_info->assigned_tlli || tlli_info->assigned_tlli != tlli)
+ if (!tlli_state->assigned || tlli_state->assigned != tlli)
return;
+ /* TODO: Is this ok? Check spec */
if (gprs_tlli_type(tlli) != TLLI_LOCAL)
return;
/* See GSM 04.08, 4.7.1.5 */
if (to_bss)
- tlli_info->net_validated = 1;
+ tlli_state->net_validated = 1;
else
- tlli_info->bss_validated = 1;
+ tlli_state->bss_validated = 1;
- if (!tlli_info->bss_validated || !tlli_info->net_validated)
+ if (!tlli_state->bss_validated || !tlli_state->net_validated)
return;
LOGP(DGPRS, LOGL_INFO,
"The TLLI %08x has been validated (was %08x)\n",
- tlli_info->assigned_tlli, tlli_info->tlli);
+ tlli_state->assigned, tlli_state->current);
- tlli_info->tlli = tlli;
- tlli_info->assigned_tlli = 0;
+ tlli_state->current = tlli;
+ tlli_state->assigned = 0;
}
void gbprox_touch_tlli(struct gbproxy_peer *peer,
struct gbproxy_tlli_info *tlli_info, time_t now)
{
- gbprox_get_detached_tlli_info(peer, tlli_info, tlli_info->tlli);
+ gbprox_get_detached_tlli_info(peer, tlli_info, 0);
gbprox_attach_tlli_info(peer, now, tlli_info);
}
@@ -727,8 +745,8 @@ struct gbproxy_tlli_info *gbprox_register_tlli(
/* TLLI has changed somehow, adjust it */
LOGP(DGPRS, LOGL_INFO,
"The TLLI has changed from %08x to %08x\n",
- tlli_info->tlli, tlli);
- tlli_info->tlli = tlli;
+ tlli_info->tlli.current, tlli);
+ tlli_info->tlli.current = tlli;
}
}
@@ -1313,6 +1331,9 @@ static int gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
return have_patched;
if (parse_ctx->raid_enc) {
+ /* TODO: BSS->SGSN: Only patch if matches original BSSGP,
+ * don't update internal mapping, patch to invalid if P-TMSI
+ * unknown. */
gbprox_patch_raid(parse_ctx->raid_enc, peer, parse_ctx->to_bss,
parse_ctx->llc_msg_name);
have_patched = 1;
@@ -1406,15 +1427,25 @@ static void gbprox_log_parse_context(struct gbproxy_parse_context *parse_ctx,
LOGP(DGPRS, LOGL_DEBUG, "\n");
}
-static struct gbproxy_tlli_info *gbprox_update_state(
- struct gbproxy_peer *peer, time_t now,
+static uint32_t gbprox_make_bss_ptmsi(struct gbproxy_peer *peer,
+ uint32_t sgsn_ptmsi)
+{
+ return sgsn_ptmsi;
+}
+
+static uint32_t gbprox_make_sgsn_tlli(struct gbproxy_peer *peer,
+ uint32_t bss_tlli)
+{
+ return bss_tlli;
+}
+
+static struct gbproxy_tlli_info *gbprox_update_state_ul(
+ struct gbproxy_peer *peer,
+ time_t now,
struct gbproxy_parse_context *parse_ctx)
{
struct gbproxy_tlli_info *tlli_info = NULL;
- if (!peer->cfg->check_imsi)
- return NULL;
-
if (parse_ctx->tlli_enc)
tlli_info = gbprox_find_tlli(peer, parse_ctx->tlli);
@@ -1424,6 +1455,69 @@ static struct gbproxy_tlli_info *gbprox_update_state(
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REQS]);
break;
+ default:
+ break;
+ }
+ }
+
+ gbprox_log_parse_context(parse_ctx, "BSSGP");
+
+ if (parse_ctx->tlli_enc && parse_ctx->llc) {
+ uint32_t sgsn_tlli;
+ if (!tlli_info) {
+ tlli_info =
+ gbprox_register_tlli(peer, parse_ctx->tlli,
+ parse_ctx->imsi,
+ parse_ctx->imsi_len, now);
+ /* Setup TLLIs */
+ sgsn_tlli = gbprox_make_sgsn_tlli(peer, parse_ctx->tlli);
+ tlli_info->sgsn_tlli.current = sgsn_tlli;
+ } else {
+ sgsn_tlli = tlli_info->sgsn_tlli.assigned;
+ if (!sgsn_tlli)
+ sgsn_tlli = tlli_info->sgsn_tlli.current;
+ if (!sgsn_tlli) {
+ sgsn_tlli = gbprox_make_sgsn_tlli(peer,
+ parse_ctx->tlli);
+ }
+
+ gbprox_validate_tlli(&tlli_info->tlli,
+ parse_ctx->tlli, 0);
+ gbprox_validate_tlli(&tlli_info->sgsn_tlli,
+ sgsn_tlli, 0);
+ gbprox_touch_tlli(peer, tlli_info, now);
+ }
+ } else if (tlli_info) {
+ gbprox_touch_tlli(peer, tlli_info, now);
+ }
+
+ if (parse_ctx->imsi && tlli_info && tlli_info->mi_data_len == 0) {
+ int enable_patching;
+ gbprox_update_tlli_info(tlli_info,
+ parse_ctx->imsi, parse_ctx->imsi_len);
+
+ /* Check, whether the IMSI matches */
+ enable_patching = gbprox_check_imsi(peer, parse_ctx->imsi,
+ parse_ctx->imsi_len);
+ if (enable_patching >= 0)
+ tlli_info->enable_patching = enable_patching;
+ }
+
+ return tlli_info;
+}
+
+static struct gbproxy_tlli_info *gbprox_update_state_dl(
+ struct gbproxy_peer *peer,
+ time_t now,
+ struct gbproxy_parse_context *parse_ctx)
+{
+ struct gbproxy_tlli_info *tlli_info = NULL;
+
+ if (parse_ctx->tlli_enc)
+ tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
+
+ if (parse_ctx->g48_hdr) {
+ switch (parse_ctx->g48_hdr->msg_type) {
case GSM48_MT_GMM_ATTACH_REJ:
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REJS]);
break;
@@ -1435,43 +1529,69 @@ static struct gbproxy_tlli_info *gbprox_update_state(
gbprox_log_parse_context(parse_ctx, "BSSGP");
- if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc &&
- parse_ctx->to_bss) {
+ if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc) {
/* A new PTMSI has been signaled in the message,
* register new TLLI */
- uint32_t new_ptmsi;
- uint32_t new_tlli;
+ uint32_t new_sgsn_ptmsi;
+ uint32_t new_sgsn_tlli;
+ uint32_t new_bss_ptmsi;
+ uint32_t new_bss_tlli = 0;
if (!parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
- &new_ptmsi)) {
+ &new_sgsn_ptmsi)) {
LOGP(DGPRS, LOGL_ERROR,
"Failed to parse new TLLI/PTMSI (current is %08x)\n",
parse_ctx->tlli);
return tlli_info;
}
- new_tlli = gprs_tmsi2tlli(new_ptmsi, TLLI_LOCAL);
+ new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
+ new_bss_ptmsi = gbprox_make_bss_ptmsi(peer, new_sgsn_ptmsi);
+ if (new_bss_ptmsi != GSM_RESERVED_TMSI)
+ new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
LOGP(DGPRS, LOGL_INFO,
- "Got new TLLI/PTMSI %08x/%08x (current is %08x)\n",
- new_tlli, new_ptmsi, parse_ctx->tlli);
+ "Got new TLLI(PTMSI) %08x(%08x) from SGSN, using %08x(%08x)\n",
+ new_sgsn_tlli, new_sgsn_ptmsi, new_bss_tlli, new_bss_ptmsi);
if (tlli_info) {
- gbprox_reassign_tlli(tlli_info, peer, new_tlli);
+ gbprox_reassign_tlli(&tlli_info->sgsn_tlli,
+ peer, new_sgsn_tlli);
+ gbprox_reassign_tlli(&tlli_info->tlli,
+ peer, new_bss_tlli);
gbprox_touch_tlli(peer, tlli_info, now);
} else {
tlli_info =
- gbprox_register_tlli(peer, new_tlli,
+ gbprox_register_tlli(peer, new_bss_tlli,
parse_ctx->imsi,
parse_ctx->imsi_len, now);
+ /* Setup TLLIs */
+ tlli_info->sgsn_tlli.current = new_sgsn_tlli;
}
- } else if (parse_ctx->tlli_enc && parse_ctx->llc) {
- if (!tlli_info) {
- tlli_info =
- gbprox_register_tlli(peer, parse_ctx->tlli,
- parse_ctx->imsi,
- parse_ctx->imsi_len, now);
- } else {
- gbprox_validate_tlli(tlli_info, parse_ctx->tlli,
- parse_ctx->to_bss);
- gbprox_touch_tlli(peer, tlli_info, now);
+ /* Setup PTMSIs */
+ tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
+ tlli_info->tlli.ptmsi = new_bss_ptmsi;
+ } else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info) {
+ /* Unknown SGSN TLLI */
+ tlli_info =
+ gbprox_register_tlli(peer, parse_ctx->tlli,
+ parse_ctx->imsi,
+ parse_ctx->imsi_len, now);
+
+ /* Setup TLLIs */
+ tlli_info->sgsn_tlli.current = tlli_info->tlli.current;
+ if (peer->cfg->patch_ptmsi) {
+ /* TODO: We don't know the local TLLI here, perhaps add
+ * a workaround that derives a PTMSI from the SGSN TLLI
+ * and use that to get the missing values. This may
+ * only happen when the gbproxy has been restarted or a
+ * tlli_info has been discarded due to age or queue
+ * length.
+ */
+ tlli_info->tlli.current = 0;
}
+ } else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
+ gbprox_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
+ if (!peer->cfg->patch_ptmsi)
+ gbprox_validate_tlli(&tlli_info->tlli,
+ parse_ctx->tlli, 1);
+ gbprox_touch_tlli(peer, tlli_info, now);
} else if (tlli_info) {
gbprox_touch_tlli(peer, tlli_info, now);
}
@@ -1662,22 +1782,23 @@ patch_error:
"Failed to patch BSSGP message as requested: %s.\n", err_info);
}
-/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
-static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
- struct msgb *msg,
- struct gbproxy_peer *peer, int to_bss)
+/* patch BSSGP message */
+static void gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
+ struct msgb *msg,
+ struct gbproxy_peer *peer)
{
struct gbproxy_parse_context parse_ctx = {0};
int rc;
int len_change = 0;
time_t now;
- struct gbproxy_tlli_info *tlli_info;
+ struct gbproxy_tlli_info *tlli_info = NULL;
if (!cfg->core_mcc && !cfg->core_mnc && !cfg->core_apn)
return;
- parse_ctx.to_bss = to_bss;
+ parse_ctx.to_bss = 0;
+ /* Parse BSSGP/LLC */
rc = gbprox_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
&parse_ctx);
@@ -1689,10 +1810,11 @@ static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
}
}
+ /* Get peer */
if (!peer && msgb_bvci(msg) >= 2)
peer = peer_by_bvci(cfg, msgb_bvci(msg));
- if (!peer && !to_bss)
+ if (!peer)
peer = gbprox_peer_by_nsei(cfg, msgb_nsei(msg));
if (!peer)
@@ -1700,9 +1822,61 @@ static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
if (!peer) {
LOGP(DLLC, LOGL_INFO,
- "NSEI=%d(%s) patching: didn't find peer for message, "
+ "NSEI=%d(BSS) patching: didn't find peer for message, "
+ "PDU %d\n",
+ msgb_nsei(msg), parse_ctx.pdu_type);
+ /* Increment counter */
+ rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
+ return;
+ }
+
+ now = time(NULL);
+
+ tlli_info = gbprox_update_state_ul(peer, now, &parse_ctx);
+
+ gbprox_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
+ peer, tlli_info, &len_change, &parse_ctx);
+
+ gbprox_update_state_after(peer, tlli_info, now, &parse_ctx);
+
+ return;
+}
+
+/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
+static void gbprox_process_bssgp_dl(struct gbproxy_config *cfg,
+ struct msgb *msg,
+ struct gbproxy_peer *peer)
+{
+ struct gbproxy_parse_context parse_ctx = {0};
+ int rc;
+ int len_change = 0;
+ time_t now;
+ struct gbproxy_tlli_info *tlli_info = NULL;
+
+ parse_ctx.to_bss = 1;
+
+ rc = gbprox_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
+ &parse_ctx);
+
+ if (!rc) {
+ if (!parse_ctx.need_decryption) {
+ LOGP(DGPRS, LOGL_ERROR,
+ "Failed to parse BSSGP/GMM message\n");
+ return;
+ }
+ }
+
+ if (!peer && msgb_bvci(msg) >= 2)
+ peer = peer_by_bvci(cfg, msgb_bvci(msg));
+
+ if (!peer)
+ peer = peer_by_bssgp_tlv(cfg, &parse_ctx.bssgp_tp);
+
+ if (!peer) {
+ LOGP(DLLC, LOGL_INFO,
+ "NSEI=%d(SGSN) patching: didn't find peer for message, "
"PDU %d\n",
- msgb_nsei(msg), to_bss ? "SGSN" : "BSS", parse_ctx.pdu_type);
+ msgb_nsei(msg), parse_ctx.pdu_type);
/* Increment counter */
rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
return;
@@ -1710,7 +1884,7 @@ static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
now = time(NULL);
- tlli_info = gbprox_update_state(peer, now, &parse_ctx);
+ tlli_info = gbprox_update_state_dl(peer, now, &parse_ctx);
gbprox_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
peer, tlli_info, &len_change, &parse_ctx);
@@ -1729,7 +1903,7 @@ static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
struct msgb *msg = gprs_msgb_copy(old_msg, "msgb_relay2sgsn");
int rc;
- gbprox_process_bssgp_message(cfg, msg, peer, 0);
+ gbprox_process_bssgp_ul(cfg, msg, peer);
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
msgb_nsei(msg), ns_bvci, cfg->nsip_sgsn_nsei);
@@ -2147,7 +2321,7 @@ int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei,
int remote_end_is_sgsn = nsei == cfg->nsip_sgsn_nsei;
if (remote_end_is_sgsn)
- gbprox_process_bssgp_message(cfg, msg, NULL, 1);
+ gbprox_process_bssgp_dl(cfg, msg, NULL);
/* Only BVCI=0 messages need special treatment */
if (ns_bvci == 0 || ns_bvci == 1) {
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index 9574a451f..d1b912fcd 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -377,7 +377,7 @@ DEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis",
snprintf(mi_buf, sizeof(mi_buf), "(none)");
}
vty_out(vty, " TLLI %08x, IMSI %s, AGE %d%s",
- tlli_info->tlli, mi_buf, (int)age,
+ tlli_info->tlli.current, mi_buf, (int)age,
VTY_NEWLINE);
}
}
@@ -532,7 +532,7 @@ DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
}
llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list) {
- if (match == MATCH_TLLI && tlli_info->tlli != tlli)
+ if (match == MATCH_TLLI && tlli_info->tlli.current != tlli)
continue;
if (match == MATCH_IMSI) {
@@ -544,7 +544,8 @@ DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
if (strcmp(mi_buf, imsi) != 0)
continue;
}
- vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli, VTY_NEWLINE);
+ vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli.current,
+ VTY_NEWLINE);
gbprox_delete_tlli(peer, tlli_info);
found += 1;
}
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c
index ed30af8de..2a521eeec 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.c
+++ b/openbsc/tests/gbproxy/gbproxy_test.c
@@ -127,9 +127,16 @@ static int dump_peers(FILE *stream, int indent, time_t now,
snprintf(mi_buf, sizeof(mi_buf), "(none)");
}
fprintf(stream, "%*s TLLI %08x",
- indent, "", tlli_info->tlli);
- if (tlli_info->assigned_tlli)
- fprintf(stream, "/%08x", tlli_info->assigned_tlli);
+ indent, "", tlli_info->tlli.current);
+ if (tlli_info->tlli.assigned)
+ fprintf(stream, "/%08x", tlli_info->tlli.assigned);
+ if (tlli_info->sgsn_tlli.current) {
+ fprintf(stream, " -> %08x",
+ tlli_info->sgsn_tlli.current);
+ if (tlli_info->sgsn_tlli.assigned)
+ fprintf(stream, "/%08x",
+ tlli_info->sgsn_tlli.assigned);
+ }
rc = fprintf(stream, ", IMSI %s, AGE %d\n",
mi_buf, (int)age);
if (rc < 0)
@@ -1115,6 +1122,7 @@ static void test_gbproxy_ra_patching()
gbcfg.core_mnc = 456;
gbcfg.core_apn = talloc_zero_size(NULL, 100);
gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
+ gbcfg.patch_ptmsi = 0;
configure_sgsn_peer(&sgsn_peer);
configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
@@ -1173,24 +1181,32 @@ static void test_gbproxy_ra_patching()
GPRS_SAPI_GMM, 1,
dtap_attach_acc, sizeof(dtap_attach_acc));
- tlli_info = gbprox_find_tlli(peer, local_tlli);
+ tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
- OSMO_ASSERT(tlli_info->tlli != local_tlli);
- OSMO_ASSERT(!tlli_info->bss_validated);
- OSMO_ASSERT(!tlli_info->net_validated);
+ OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
+ OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
+ OSMO_ASSERT(!tlli_info->tlli.bss_validated);
+ OSMO_ASSERT(!tlli_info->tlli.net_validated);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
+ OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
+ OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
local_tlli, &rai_bss, cell_id,
GPRS_SAPI_GMM, 4,
dtap_attach_complete, sizeof(dtap_attach_complete));
- tlli_info = gbprox_find_tlli(peer, local_tlli);
+ tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
- OSMO_ASSERT(tlli_info->tlli != local_tlli);
- OSMO_ASSERT(tlli_info->bss_validated);
- OSMO_ASSERT(!tlli_info->net_validated);
+ OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
+ OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
+ OSMO_ASSERT(tlli_info->tlli.bss_validated);
+ OSMO_ASSERT(!tlli_info->tlli.net_validated);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
+ OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
/* Replace APN (1) */
send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
@@ -1198,22 +1214,28 @@ static void test_gbproxy_ra_patching()
GPRS_SAPI_GMM, 3,
dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
- tlli_info = gbprox_find_tlli(peer, local_tlli);
+ tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
- OSMO_ASSERT(tlli_info->tlli != local_tlli);
- OSMO_ASSERT(tlli_info->bss_validated);
- OSMO_ASSERT(!tlli_info->net_validated);
+ OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
+ OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
+ OSMO_ASSERT(tlli_info->tlli.bss_validated);
+ OSMO_ASSERT(!tlli_info->tlli.net_validated);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
+ OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
local_tlli, 1, imsi, sizeof(imsi),
GPRS_SAPI_GMM, 2,
dtap_gmm_information, sizeof(dtap_gmm_information));
- tlli_info = gbprox_find_tlli(peer, local_tlli);
+ tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->assigned_tlli == 0);
- OSMO_ASSERT(tlli_info->tlli == local_tlli);
+ OSMO_ASSERT(tlli_info->tlli.assigned == 0);
+ OSMO_ASSERT(tlli_info->tlli.current == local_tlli);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
+ OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_tlli);
/* Replace APN (2) */
send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
@@ -1566,7 +1588,7 @@ static void test_gbproxy_tlli_expire(void)
tlli_info = gbprox_register_tlli(peer, tlli1,
imsi1, ARRAY_SIZE(imsi1), now);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli1);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli1);
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
/* replace the old entry */
@@ -1574,7 +1596,7 @@ static void test_gbproxy_tlli_expire(void)
tlli_info = gbprox_register_tlli(peer, tlli2,
imsi1, ARRAY_SIZE(imsi1), now);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli2);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli2);
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
dump_peers(stdout, 2, now, &cfg);
@@ -1582,7 +1604,7 @@ static void test_gbproxy_tlli_expire(void)
/* verify that 5678 has survived */
tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli2);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli2);
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
OSMO_ASSERT(!tlli_info);
@@ -1605,7 +1627,7 @@ static void test_gbproxy_tlli_expire(void)
tlli_info = gbprox_register_tlli(peer, tlli1,
imsi1, ARRAY_SIZE(imsi1), now);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli1);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli1);
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
/* try to replace the old entry */
@@ -1613,7 +1635,7 @@ static void test_gbproxy_tlli_expire(void)
tlli_info = gbprox_register_tlli(peer, tlli1,
imsi2, ARRAY_SIZE(imsi2), now);
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli1);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli1);
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
dump_peers(stdout, 2, now, &cfg);
@@ -1623,7 +1645,7 @@ static void test_gbproxy_tlli_expire(void)
OSMO_ASSERT(!tlli_info);
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli1);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli1);
printf("\n");
@@ -1661,7 +1683,7 @@ static void test_gbproxy_tlli_expire(void)
OSMO_ASSERT(!tlli_info);
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
OSMO_ASSERT(tlli_info);
- OSMO_ASSERT(tlli_info->tlli == tlli2);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli2);
printf("\n");
@@ -1669,6 +1691,7 @@ static void test_gbproxy_tlli_expire(void)
}
{
+ struct gbproxy_tlli_info *tlli_info;
int num_removed;
printf("Test TLLI expiry, max_age == 1:\n");
@@ -1693,12 +1716,20 @@ static void test_gbproxy_tlli_expire(void)
dump_peers(stdout, 2, now + 2, &cfg);
+ /* verify that 5678 has survived */
+ tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
+ OSMO_ASSERT(!tlli_info);
+ tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
+ OSMO_ASSERT(tlli_info);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli2);
+
printf("\n");
gbproxy_peer_free(peer);
}
{
+ struct gbproxy_tlli_info *tlli_info;
int num_removed;
printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
@@ -1731,6 +1762,15 @@ static void test_gbproxy_tlli_expire(void)
dump_peers(stdout, 2, now + 2, &cfg);
+ /* verify that tlli3 has survived */
+ tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
+ OSMO_ASSERT(!tlli_info);
+ tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
+ OSMO_ASSERT(!tlli_info);
+ tlli_info = gbprox_find_tlli_by_mi(peer, imsi3, ARRAY_SIZE(imsi3));
+ OSMO_ASSERT(tlli_info);
+ OSMO_ASSERT(tlli_info->tlli.current == tlli3);
+
printf("\n");
gbproxy_peer_free(peer);
diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok
index 74e895505..b9919060e 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.ok
+++ b/openbsc/tests/gbproxy/gbproxy_test.ok
@@ -1745,7 +1745,7 @@ Peers:
Attach Request count : 1
TLLI cache size : 1
TLLI-Cache: 1
- TLLI efe2b700, IMSI 12131415161718, AGE 0
+ TLLI efe2b700 -> efe2b700, 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
@@ -1823,7 +1823,7 @@ Peers:
Attach Request count : 1
TLLI cache size : 1
TLLI-Cache: 1
- TLLI bbc54679/efe2b700, IMSI 12131415161718, AGE 0
+ TLLI bbc54679/efe2b700 -> bbc54679/efe2b700, IMSI 12131415161718, AGE 0
PROCESSING DETACH REQ (PWR OFF) 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 09 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 84 0c eb
@@ -1883,7 +1883,7 @@ Peers:
Attach Request count : 1
TLLI cache size : 1
TLLI-Cache: 1
- TLLI efe2b700, IMSI (none), AGE 0
+ TLLI efe2b700 -> efe2b700, IMSI (none), AGE 0
Test TLLI info expiry
Test TLLI replacement: