diff options
Diffstat (limited to 'openbsc/src/gprs/gb_proxy.c')
-rw-r--r-- | openbsc/src/gprs/gb_proxy.c | 307 |
1 files changed, 18 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; } - |