aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gb_proxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gprs/gb_proxy.c')
-rw-r--r--openbsc/src/gprs/gb_proxy.c307
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;
}
-