diff options
Diffstat (limited to 'openbsc/src/gprs')
-rw-r--r-- | openbsc/src/gprs/gb_proxy.c | 307 | ||||
-rw-r--r-- | openbsc/src/gprs/gb_proxy_main.c | 1 | ||||
-rw-r--r-- | openbsc/src/gprs/gb_proxy_vty.c | 235 |
3 files changed, 254 insertions, 289 deletions
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index d4b5e0e40..3e5afa485 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -35,8 +35,6 @@ #include <osmocom/core/select.h> #include <osmocom/core/rate_ctr.h> -#include <osmocom/vty/misc.h> - #include <osmocom/gprs/gprs_ns.h> #include <osmocom/gprs/gprs_bssgp.h> @@ -89,7 +87,7 @@ static const struct rate_ctr_group_desc global_ctrg_desc = { static struct rate_ctr_group *global_ctrg = NULL; -static struct rate_ctr_group *get_global_ctrg() +struct rate_ctr_group *get_global_ctrg(void) { if (global_ctrg) return global_ctrg; @@ -142,36 +140,6 @@ struct { regex_t imsi_re_comp; } gbprox_global_patch_state = {0,}; -struct gbprox_patch_state { - int local_mnc; - int local_mcc; - - /* List of TLLIs for which patching is enabled */ - struct llist_head enabled_tllis; - int enabled_tllis_count; -}; - -struct gbprox_peer { - struct llist_head list; - - /* NSEI of the peer entity */ - uint16_t nsei; - - /* BVCI used for Point-to-Point to this peer */ - uint16_t bvci; - int blocked; - - /* Routeing Area that this peer is part of (raw 04.08 encoding) */ - uint8_t ra[6]; - - /* Counter */ - struct rate_ctr_group *ctrg; - - struct gbprox_patch_state patch_state; -}; - -/* Linked list of all Gb peers (except SGSN) */ -static LLIST_HEAD(gbprox_bts_peers); static void gbprox_delete_tllis(struct gbprox_peer *peer); @@ -179,7 +147,7 @@ static void gbprox_delete_tllis(struct gbprox_peer *peer); static struct gbprox_peer *peer_by_bvci(uint16_t bvci) { struct gbprox_peer *peer; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { if (peer->bvci == bvci) return peer; } @@ -187,10 +155,10 @@ static struct gbprox_peer *peer_by_bvci(uint16_t bvci) } /* Find the gbprox_peer by its NSEI */ -static struct gbprox_peer *peer_by_nsei(uint16_t nsei) +struct gbprox_peer *peer_by_nsei(uint16_t nsei) { struct gbprox_peer *peer; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { if (peer->nsei == nsei) return peer; } @@ -201,7 +169,7 @@ static struct gbprox_peer *peer_by_nsei(uint16_t nsei) static struct gbprox_peer *peer_by_rai(const uint8_t *ra) { struct gbprox_peer *peer; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { if (!memcmp(peer->ra, ra, 6)) return peer; } @@ -212,7 +180,7 @@ static struct gbprox_peer *peer_by_rai(const uint8_t *ra) static struct gbprox_peer *peer_by_lai(const uint8_t *la) { struct gbprox_peer *peer; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { if (!memcmp(peer->ra, la, 5)) return peer; } @@ -223,7 +191,7 @@ static struct gbprox_peer *peer_by_lai(const uint8_t *la) static struct gbprox_peer *peer_by_lac(const uint8_t *la) { struct gbprox_peer *peer; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { if (!memcmp(peer->ra + 3, la + 3, 2)) return peer; } @@ -255,7 +223,7 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) peer->bvci = bvci; peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci); - llist_add(&peer->list, &gbprox_bts_peers); + llist_add(&peer->list, &gbcfg.bts_peers); INIT_LLIST_HEAD(&peer->patch_state.enabled_tllis); @@ -551,15 +519,6 @@ struct gbprox_parse_context { uint32_t new_ptmsi; }; -struct gbprox_tlli_info { - struct llist_head list; - - uint32_t tlli; - time_t timestamp; - uint8_t *mi_data; - size_t mi_data_len; -}; - static struct gbprox_tlli_info *gbprox_find_tlli(struct gbprox_peer *peer, uint32_t tlli) { @@ -593,7 +552,7 @@ static struct gbprox_tlli_info *gbprox_find_tlli_by_mi( return NULL; } -static void gbprox_delete_tlli(struct gbprox_peer *peer, +void gbprox_delete_tlli(struct gbprox_peer *peer, struct gbprox_tlli_info *tlli_info) { struct gbprox_patch_state *state = &peer->patch_state; @@ -676,7 +635,7 @@ static int gbprox_check_imsi(struct gbprox_peer *peer, return 1; } -static int gbprox_remove_stale_ttlis(struct gbprox_peer *peer, time_t now) +int gbprox_remove_stale_ttlis(struct gbprox_peer *peer, time_t now) { struct gbprox_patch_state *state = &peer->patch_state; struct gbprox_tlli_info *tlli_info = NULL, *nxt; @@ -1740,7 +1699,7 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, * from the SGSN. As the signalling BVCI is shared * among all the BSS's that we multiplex, it needs to * be relayed */ - llist_for_each_entry(peer, &gbprox_bts_peers, list) + llist_for_each_entry(peer, &gbcfg.bts_peers, list) gbprox_relay2peer(msg, peer, ns_bvci); return 0; @@ -2050,7 +2009,7 @@ int gbprox_dump_peers(FILE *stream, int indent) if (rc < 0) return rc; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { struct gbprox_tlli_info *tlli_info; struct gbprox_patch_state *state = &peer->patch_state; gsm48_parse_ra(&raid, peer->ra); @@ -2105,19 +2064,19 @@ void gbprox_reset() { struct gbprox_peer *peer, *tmp; - llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) + llist_for_each_entry_safe(peer, tmp, &gbcfg.bts_peers, list) peer_free(peer); rate_ctr_group_free(global_ctrg); global_ctrg = NULL; } -static int gbprox_cleanup_peers(uint16_t nsei, uint16_t bvci) +int gbprox_cleanup_peers(uint16_t nsei, uint16_t bvci) { int counter = 0; struct gbprox_peer *peer, *tmp; - llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) { + llist_for_each_entry_safe(peer, tmp, &gbcfg.bts_peers, list) { if (peer->nsei != nsei) continue; if (bvci && peer->bvci != bvci) @@ -2130,238 +2089,8 @@ static int gbprox_cleanup_peers(uint16_t nsei, uint16_t bvci) return counter; } -#include <osmocom/vty/command.h> - -static void gbprox_vty_print_peer(struct vty *vty, struct gbprox_peer *peer) -{ - struct gprs_ra_id raid; - gsm48_parse_ra(&raid, peer->ra); - - vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " - "RAI %u-%u-%u-%u", - peer->nsei, peer->bvci, - raid.mcc, raid.mnc, raid.lac, raid.rac); - if (peer->blocked) - vty_out(vty, " [BVC-BLOCKED]"); - - vty_out(vty, "%s", VTY_NEWLINE); -} - -gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", - SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n") -{ - struct gbprox_peer *peer; - int show_stats = argc >= 1; - - if (show_stats) - vty_out_rate_ctr_group(vty, "", get_global_ctrg()); - - llist_for_each_entry(peer, &gbprox_bts_peers, list) { - gbprox_vty_print_peer(vty, peer); - - if (show_stats) - vty_out_rate_ctr_group(vty, " ", peer->ctrg); - } - return CMD_SUCCESS; -} - -gDEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis", - SHOW_STR "Display information about the Gb proxy\n" "Show TLLIs\n") -{ - struct gbprox_peer *peer; - char mi_buf[200]; - time_t now = time(NULL); - - llist_for_each_entry(peer, &gbprox_bts_peers, list) { - struct gbprox_tlli_info *tlli_info; - struct gbprox_patch_state *state = &peer->patch_state; - - gbprox_vty_print_peer(vty, peer); - - 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); - vty_out(vty, " TLLI %08x, IMSI %s, AGE %d%s", - tlli_info->tlli, mi_buf, (int)age, - VTY_NEWLINE); - } - } - return CMD_SUCCESS; -} - -gDEFUN(delete_gb_bvci, delete_gb_bvci_cmd, - "delete-gbproxy-peer <0-65534> bvci <2-65534>", - "Delete a GBProxy peer by NSEI and optionally BVCI\n" - "NSEI number\n" - "Only delete peer with a matching BVCI\n" - "BVCI number\n") -{ - const uint16_t nsei = atoi(argv[0]); - const uint16_t bvci = atoi(argv[1]); - int counter; - - counter = gbprox_cleanup_peers(nsei, bvci); - - if (counter == 0) { - vty_out(vty, "BVC not found%s", VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -gDEFUN(delete_gb_nsei, delete_gb_nsei_cmd, - "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]", - "Delete a GBProxy peer by NSEI and optionally BVCI\n" - "NSEI number\n" - "Only delete BSSGP connections (BVC)\n" - "Only delete dynamic NS connections (NS-VC)\n" - "Delete BVC and dynamic NS connections\n" - "Show what would be deleted instead of actually deleting\n" - ) +int gbproxy_init_config(struct gbproxy_config *cfg) { - const uint16_t nsei = atoi(argv[0]); - const char *mode = argv[1]; - int dry_run = argc > 2; - int delete_bvc = 0; - int delete_nsvc = 0; - int counter; - - if (strcmp(mode, "only-bvc") == 0) - delete_bvc = 1; - else if (strcmp(mode, "only-nsvc") == 0) - delete_nsvc = 1; - else - delete_bvc = delete_nsvc = 1; - - if (delete_bvc) { - if (!dry_run) - counter = gbprox_cleanup_peers(nsei, 0); - else { - struct gbprox_peer *peer; - counter = 0; - llist_for_each_entry(peer, &gbprox_bts_peers, list) { - if (peer->nsei != nsei) - continue; - - vty_out(vty, "BVC: "); - gbprox_vty_print_peer(vty, peer); - counter += 1; - } - } - vty_out(vty, "%sDeleted %d BVC%s", - dry_run ? "Not " : "", counter, VTY_NEWLINE); - } - - if (delete_nsvc) { - struct gprs_ns_inst *nsi = gbcfg.nsi; - struct gprs_nsvc *nsvc, *nsvc2; - - counter = 0; - llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) { - if (nsvc->nsei != nsei) - continue; - if (nsvc->persistent) - continue; - - if (!dry_run) - gprs_nsvc_delete(nsvc); - else - vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, " - "remote %s%s", - nsvc->nsei, nsvc->nsvci, - gprs_ns_ll_str(nsvc), VTY_NEWLINE); - counter += 1; - } - vty_out(vty, "%sDeleted %d NS-VC%s", - dry_run ? "Not " : "", counter, VTY_NEWLINE); - } - - return CMD_SUCCESS; -} - -gDEFUN(delete_gb_tlli, delete_gb_tlli_cmd, - "delete-gbproxy-tlli <0-65534> (tlli|imsi|stale) [IDENT]", - "Delete a GBProxy TLLI entry by NSEI and identification\n" - "NSEI number\n" - "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_STALE = 's'} match; - uint32_t tlli = 0; - const char *imsi = NULL; - struct gbprox_peer *peer = 0; - struct gbprox_tlli_info *tlli_info, *nxt; - struct gbprox_patch_state *state; - char mi_buf[200]; - int found = 0; - - match = argv[1][0]; - - switch (match) { - case MATCH_TLLI: - if (argc < 2 || !argv[2][0]) { - vty_out(vty, "%% Missing TLLI%s", VTY_NEWLINE); - return CMD_WARNING; - } - tlli = strtoll(argv[2], NULL, 16); - break; - case MATCH_IMSI: - if (argc < 2 || !argv[2][0]) { - vty_out(vty, "%% Missing IMSI%s", VTY_NEWLINE); - return CMD_WARNING; - } - imsi = argv[2]; - break; - default: - break; - } - - peer = peer_by_nsei(nsei); - if (!peer) { - vty_out(vty, "Didn't find peer with NSEI %d%s", - nsei, VTY_NEWLINE); - return CMD_WARNING; - } - - state = &peer->patch_state; - - if (match == MATCH_STALE) { - found = gbprox_remove_stale_ttlis(peer, time(NULL)); - if (found) - vty_out(vty, "Deleted %d stale TLLI%s%s", - found, found == 1 ? "" : "s", VTY_NEWLINE); - return CMD_SUCCESS; - } - - llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list) { - if (match == MATCH_TLLI && tlli_info->tlli != tlli) - continue; - - if (match == MATCH_IMSI) { - mi_buf[0] = '\0'; - gsm48_mi_to_string(mi_buf, sizeof(mi_buf), - tlli_info->mi_data, - tlli_info->mi_data_len); - - if (strcmp(mi_buf, imsi) != 0) - continue; - } - vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli, VTY_NEWLINE); - gbprox_delete_tlli(peer, tlli_info); - found += 1; - } - - if (!found && argc >= 2) { - vty_out(vty, "Didn't find TLLI entry with %s %s%s", - argv[1], argv[2], VTY_NEWLINE); - } - - return CMD_SUCCESS; + INIT_LLIST_HEAD(&cfg->bts_peers); + return 0; } - diff --git a/openbsc/src/gprs/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c index 1f140d48d..773c98336 100644 --- a/openbsc/src/gprs/gb_proxy_main.c +++ b/openbsc/src/gprs/gb_proxy_main.c @@ -259,6 +259,7 @@ int main(int argc, char **argv) LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n"); exit(1); } + gbproxy_init_config(&gbcfg); gbcfg.nsi = bssgp_nsi; gprs_ns_vty_init(bssgp_nsi); gprs_ns_set_log_ss(DNS); diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index e7506fc3e..16d8ceeb1 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -22,9 +22,12 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> +#include <time.h> #include <osmocom/core/talloc.h> +#include <osmocom/core/rate_ctr.h> +#include <openbsc/gsm_04_08.h> #include <osmocom/gprs/gprs_ns.h> #include <openbsc/debug.h> @@ -33,6 +36,7 @@ #include <osmocom/vty/command.h> #include <osmocom/vty/vty.h> +#include <osmocom/vty/misc.h> static struct gbproxy_config *g_cfg = NULL; @@ -56,6 +60,21 @@ static const struct value_string patch_modes[] = { {0, NULL} }; +static void gbprox_vty_print_peer(struct vty *vty, struct gbprox_peer *peer) +{ + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, peer->ra); + + vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " + "RAI %u-%u-%u-%u", + peer->nsei, peer->bvci, + raid.mcc, raid.mnc, raid.lac, raid.rac); + if (peer->blocked) + vty_out(vty, " [BVC-BLOCKED]"); + + vty_out(vty, "%s", VTY_NEWLINE); +} + static int config_write_gbproxy(struct vty *vty) { vty_out(vty, "gbproxy%s", VTY_NEWLINE); @@ -315,7 +334,223 @@ DEFUN(cfg_gbproxy_patch_mode, return CMD_SUCCESS; } +DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", + SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n") +{ + struct gbprox_peer *peer; + int show_stats = argc >= 1; + + if (show_stats) + vty_out_rate_ctr_group(vty, "", get_global_ctrg()); + + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { + gbprox_vty_print_peer(vty, peer); + + if (show_stats) + vty_out_rate_ctr_group(vty, " ", peer->ctrg); + } + return CMD_SUCCESS; +} + +DEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis", + SHOW_STR "Display information about the Gb proxy\n" "Show TLLIs\n") +{ + struct gbprox_peer *peer; + char mi_buf[200]; + time_t now = time(NULL); + + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { + struct gbprox_tlli_info *tlli_info; + struct gbprox_patch_state *state = &peer->patch_state; + + gbprox_vty_print_peer(vty, peer); + + 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); + vty_out(vty, " TLLI %08x, IMSI %s, AGE %d%s", + tlli_info->tlli, mi_buf, (int)age, + VTY_NEWLINE); + } + } + return CMD_SUCCESS; +} + +DEFUN(delete_gb_bvci, delete_gb_bvci_cmd, + "delete-gbproxy-peer <0-65534> bvci <2-65534>", + "Delete a GBProxy peer by NSEI and optionally BVCI\n" + "NSEI number\n" + "Only delete peer with a matching BVCI\n" + "BVCI number\n") +{ + const uint16_t nsei = atoi(argv[0]); + const uint16_t bvci = atoi(argv[1]); + int counter; + + counter = gbprox_cleanup_peers(nsei, bvci); + + if (counter == 0) { + vty_out(vty, "BVC not found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} +DEFUN(delete_gb_nsei, delete_gb_nsei_cmd, + "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]", + "Delete a GBProxy peer by NSEI and optionally BVCI\n" + "NSEI number\n" + "Only delete BSSGP connections (BVC)\n" + "Only delete dynamic NS connections (NS-VC)\n" + "Delete BVC and dynamic NS connections\n" + "Show what would be deleted instead of actually deleting\n" + ) +{ + const uint16_t nsei = atoi(argv[0]); + const char *mode = argv[1]; + int dry_run = argc > 2; + int delete_bvc = 0; + int delete_nsvc = 0; + int counter; + + if (strcmp(mode, "only-bvc") == 0) + delete_bvc = 1; + else if (strcmp(mode, "only-nsvc") == 0) + delete_nsvc = 1; + else + delete_bvc = delete_nsvc = 1; + + if (delete_bvc) { + if (!dry_run) + counter = gbprox_cleanup_peers(nsei, 0); + else { + struct gbprox_peer *peer; + counter = 0; + llist_for_each_entry(peer, &gbcfg.bts_peers, list) { + if (peer->nsei != nsei) + continue; + + vty_out(vty, "BVC: "); + gbprox_vty_print_peer(vty, peer); + counter += 1; + } + } + vty_out(vty, "%sDeleted %d BVC%s", + dry_run ? "Not " : "", counter, VTY_NEWLINE); + } + + if (delete_nsvc) { + struct gprs_ns_inst *nsi = gbcfg.nsi; + struct gprs_nsvc *nsvc, *nsvc2; + + counter = 0; + llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei != nsei) + continue; + if (nsvc->persistent) + continue; + + if (!dry_run) + gprs_nsvc_delete(nsvc); + else + vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, " + "remote %s%s", + nsvc->nsei, nsvc->nsvci, + gprs_ns_ll_str(nsvc), VTY_NEWLINE); + counter += 1; + } + vty_out(vty, "%sDeleted %d NS-VC%s", + dry_run ? "Not " : "", counter, VTY_NEWLINE); + } + + return CMD_SUCCESS; +} + +DEFUN(delete_gb_tlli, delete_gb_tlli_cmd, + "delete-gbproxy-tlli <0-65534> (tlli|imsi|stale) [IDENT]", + "Delete a GBProxy TLLI entry by NSEI and identification\n" + "NSEI number\n" + "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_STALE = 's'} match; + uint32_t tlli = 0; + const char *imsi = NULL; + struct gbprox_peer *peer = 0; + struct gbprox_tlli_info *tlli_info, *nxt; + struct gbprox_patch_state *state; + char mi_buf[200]; + int found = 0; + + match = argv[1][0]; + + switch (match) { + case MATCH_TLLI: + if (argc < 2 || !argv[2][0]) { + vty_out(vty, "%% Missing TLLI%s", VTY_NEWLINE); + return CMD_WARNING; + } + tlli = strtoll(argv[2], NULL, 16); + break; + case MATCH_IMSI: + if (argc < 2 || !argv[2][0]) { + vty_out(vty, "%% Missing IMSI%s", VTY_NEWLINE); + return CMD_WARNING; + } + imsi = argv[2]; + break; + default: + break; + } + + peer = peer_by_nsei(nsei); + if (!peer) { + vty_out(vty, "Didn't find peer with NSEI %d%s", + nsei, VTY_NEWLINE); + return CMD_WARNING; + } + + state = &peer->patch_state; + + if (match == MATCH_STALE) { + found = gbprox_remove_stale_ttlis(peer, time(NULL)); + if (found) + vty_out(vty, "Deleted %d stale TLLI%s%s", + found, found == 1 ? "" : "s", VTY_NEWLINE); + return CMD_SUCCESS; + } + + llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list) { + if (match == MATCH_TLLI && tlli_info->tlli != tlli) + continue; + + if (match == MATCH_IMSI) { + mi_buf[0] = '\0'; + gsm48_mi_to_string(mi_buf, sizeof(mi_buf), + tlli_info->mi_data, + tlli_info->mi_data_len); + + if (strcmp(mi_buf, imsi) != 0) + continue; + } + vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli, VTY_NEWLINE); + gbprox_delete_tlli(peer, tlli_info); + found += 1; + } + + if (!found && argc >= 2) { + vty_out(vty, "Didn't find TLLI entry with %s %s%s", + argv[1], argv[2], VTY_NEWLINE); + } + + return CMD_SUCCESS; +} int gbproxy_vty_init(void) { |