aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/gprs/gb_proxy_tlli.c84
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c29
-rw-r--r--openbsc/src/gprs/gprs_gb_parse.c12
3 files changed, 110 insertions, 15 deletions
diff --git a/openbsc/src/gprs/gb_proxy_tlli.c b/openbsc/src/gprs/gb_proxy_tlli.c
index 78459b75d..509e48991 100644
--- a/openbsc/src/gprs/gb_proxy_tlli.c
+++ b/openbsc/src/gprs/gb_proxy_tlli.c
@@ -316,17 +316,28 @@ void gbproxy_touch_tlli(struct gbproxy_peer *peer,
gbproxy_attach_tlli_info(peer, now, tlli_info);
}
-static void gbproxy_unregister_tlli(struct gbproxy_peer *peer, uint32_t tlli)
+static void gbproxy_unregister_tlli(struct gbproxy_peer *peer,
+ struct gbproxy_tlli_info *tlli_info)
{
- struct gbproxy_tlli_info *tlli_info;
+ if (!tlli_info)
+ return;
- tlli_info = gbproxy_find_tlli(peer, tlli);
- if (tlli_info) {
+ if (tlli_info->tlli.ptmsi == GSM_RESERVED_TMSI && !tlli_info->imsi_len) {
LOGP(DGPRS, LOGL_INFO,
- "Removing TLLI %08x from list\n",
- tlli);
+ "Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
+ tlli_info->tlli.current);
gbproxy_delete_tlli(peer, tlli_info);
+ return;
}
+
+ tlli_info->tlli.current = 0;
+ tlli_info->tlli.assigned = 0;
+ tlli_info->sgsn_tlli.current = 0;
+ tlli_info->sgsn_tlli.assigned = 0;
+
+ tlli_info->is_deregistered = 1;
+
+ return;
}
int gbproxy_check_tlli(struct gbproxy_peer *peer,
@@ -338,21 +349,45 @@ int gbproxy_check_tlli(struct gbproxy_peer *peer,
return tlli_info != NULL && tlli_info->enable_patching;
}
-struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
+struct gbproxy_tlli_info *gbproxy_get_tlli_info_ul(
struct gbproxy_peer *peer,
- time_t now,
struct gprs_gb_parse_context *parse_ctx)
{
struct gbproxy_tlli_info *tlli_info = NULL;
- if (parse_ctx->tlli_enc) {
+ if (parse_ctx->tlli_enc)
tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
- if (!tlli_info && parse_ctx->imsi)
- tlli_info = gbproxy_find_tlli_by_imsi(
- peer, parse_ctx->imsi, parse_ctx->imsi_len);
+ if (!tlli_info && parse_ctx->imsi)
+ tlli_info = gbproxy_find_tlli_by_imsi(
+ peer, parse_ctx->imsi, parse_ctx->imsi_len);
+
+ if (!tlli_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
+ uint32_t bss_ptmsi;
+ if (!gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
+ &bss_ptmsi))
+ LOGP(DGPRS, LOGL_ERROR,
+ "Failed to parse P-TMSI (TLLI is %08x)\n",
+ parse_ctx->tlli);
+ else
+ tlli_info = gbproxy_find_tlli_by_ptmsi(peer, bss_ptmsi);
}
+ if (tlli_info)
+ tlli_info->is_deregistered = 0;
+
+ return tlli_info;
+}
+
+struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
+ struct gbproxy_peer *peer,
+ time_t now,
+ struct gprs_gb_parse_context *parse_ctx)
+{
+ struct gbproxy_tlli_info *tlli_info;
+
+ tlli_info = gbproxy_get_tlli_info_ul(peer, parse_ctx);
+
if (parse_ctx->tlli_enc && parse_ctx->llc) {
uint32_t sgsn_tlli;
if (!tlli_info) {
@@ -366,6 +401,13 @@ struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
parse_ctx->tlli);
tlli_info->sgsn_tlli.current = sgsn_tlli;
tlli_info->tlli.current = parse_ctx->tlli;;
+ } else if (!tlli_info->tlli.current) {
+ /* New TLLI (info found by IMSI or P-TMSI) */
+ tlli_info->tlli.current = parse_ctx->tlli;
+ tlli_info->sgsn_tlli.current =
+ gbproxy_make_sgsn_tlli(peer, tlli_info,
+ parse_ctx->tlli);
+ gbproxy_touch_tlli(peer, tlli_info, now);
} else {
sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
if (!sgsn_tlli)
@@ -512,8 +554,22 @@ void gbproxy_update_tlli_state_after(
time_t now,
struct gprs_gb_parse_context *parse_ctx)
{
- if (parse_ctx->invalidate_tlli) {
- gbproxy_unregister_tlli(peer, parse_ctx->tlli);
+ if (parse_ctx->invalidate_tlli && tlli_info) {
+ int keep_info =
+ peer->cfg->keep_tlli_infos == GBPROX_KEEP_ALWAYS ||
+ (peer->cfg->keep_tlli_infos == GBPROX_KEEP_REATTACH &&
+ parse_ctx->await_reattach) ||
+ (peer->cfg->keep_tlli_infos == GBPROX_KEEP_IDENTIFIED &&
+ tlli_info->imsi_len > 0);
+ if (keep_info) {
+ LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
+ tlli_info->tlli.current);
+ gbproxy_unregister_tlli(peer, tlli_info);
+ } else {
+ LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
+ tlli_info->tlli.current);
+ gbproxy_delete_tlli(peer, tlli_info);
+ }
} else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
parse_ctx->new_ptmsi_enc && tlli_info) {
/* A new PTMSI has been signaled in the message,
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index efdf751d9..ee392892c 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -50,6 +50,14 @@ static struct cmd_node gbproxy_node = {
1,
};
+static const struct value_string keep_modes[] = {
+ {GBPROX_KEEP_NEVER, "never"},
+ {GBPROX_KEEP_REATTACH, "re-attach"},
+ {GBPROX_KEEP_IDENTIFIED, "identified"},
+ {GBPROX_KEEP_ALWAYS, "always"},
+ {0, NULL}
+};
+
static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
{
struct gprs_ra_id raid;
@@ -106,6 +114,10 @@ static int config_write_gbproxy(struct vty *vty)
if (g_cfg->tlli_max_len > 0)
vty_out(vty, " tlli-list max-length %d%s",
g_cfg->tlli_max_len, VTY_NEWLINE);
+ vty_out(vty, " tlli-list keep-mode %s%s",
+ get_value_string(keep_modes, g_cfg->keep_tlli_infos),
+ VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -398,6 +410,22 @@ DEFUN(cfg_gbproxy_tlli_list_no_max_len,
return CMD_SUCCESS;
}
+DEFUN(cfg_gbproxy_tlli_list_keep_mode,
+ cfg_gbproxy_tlli_list_keep_mode_cmd,
+ "tlli-list keep-mode (never|re-attach|identified|always)",
+ GBPROXY_TLLI_LIST_STR "How to keep entries for detached TLLIs\n"
+ "Discard entry immediately after detachment\n"
+ "Keep entry if a re-attachment has be requested\n"
+ "Keep entry if it associated with an IMSI\n"
+ "Don't discard entries after detachment\n")
+{
+ int val = get_string_value(keep_modes, argv[0]);
+ OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
+ g_cfg->keep_tlli_infos = val;
+
+ return CMD_SUCCESS;
+}
+
DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
@@ -654,6 +682,7 @@ int gbproxy_vty_init(void)
install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_max_age_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_max_len_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_keep_mode_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
diff --git a/openbsc/src/gprs/gprs_gb_parse.c b/openbsc/src/gprs/gprs_gb_parse.c
index f361951a1..7ae792a62 100644
--- a/openbsc/src/gprs/gprs_gb_parse.c
+++ b/openbsc/src/gprs/gprs_gb_parse.c
@@ -224,6 +224,7 @@ static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
{
uint8_t *value;
size_t value_len;
+ int detach_type;
int power_off;
parse_ctx->llc_msg_name = "DETACH_REQ";
@@ -234,9 +235,14 @@ static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
/* invalid */
return 0;
+ detach_type = *value & 0x07;
power_off = *value & 0x08 ? 1 : 0;
- if (!parse_ctx->to_bss) {
+ if (parse_ctx->to_bss) {
+ /* Network originated */
+ if (detach_type == GPRS_DET_T_MT_REATT_REQ)
+ parse_ctx->await_reattach = 1;
+ } else {
/* Mobile originated */
if (power_off)
@@ -651,6 +657,10 @@ void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx,
LOGP(DGPRS, LOGL_DEBUG, "%s invalidate", sep);
sep = ",";
}
+ if (parse_ctx->await_reattach) {
+ LOGP(DGPRS, LOGL_DEBUG, "%s re-attach", sep);
+ sep = ",";
+ }
LOGP(DGPRS, LOGL_DEBUG, "\n");
}