aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gb_proxy_vty.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gprs/gb_proxy_vty.c')
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c235
1 files changed, 235 insertions, 0 deletions
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)
{