diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2014-09-12 15:09:56 +0200 |
---|---|---|
committer | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2014-09-19 10:46:23 +0200 |
commit | 7430da621a25337d614cd08acb578905aa52337d (patch) | |
tree | 0def31a783b198da3bf6b4c894377191743ce9f6 /openbsc/src | |
parent | cba4c0cc600da7b9548e9267cb0486806820a9ef (diff) |
gbproxy: Keep tlli_info after detach
Currently a tlli_info entry is deleted when the TLLI gets invalidated
by a Detach message.
This patch introduces the possibility to keep tlli_info entries in
the list. Those entries then have cleared TLLI fields, are marked as
de-registered, and can only be retrieved by a message containing an
IMSI or a P-TMSI.
The following VTY configuration commands are added to the gbproxy
node:
- tlli-list keep-mode never : Don't keep the entries (default)
- tlli-list keep-mode re-attach : Only keep them, when a Detach
message with re-attach required has been received
- tlli-list keep-mode identified : Only keep entries which are
associated with an IMSI
- tlli-list keep-mode always : Keep all entries
Note that at least one of max-length or max-age should be set when
this feature is used to limit the number of entries.
Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/gprs/gb_proxy_tlli.c | 84 | ||||
-rw-r--r-- | openbsc/src/gprs/gb_proxy_vty.c | 29 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_gb_parse.c | 12 |
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"); } |