aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gprs')
-rw-r--r--openbsc/src/gprs/Makefile.am3
-rw-r--r--openbsc/src/gprs/gb_proxy.c132
-rw-r--r--openbsc/src/gprs/gb_proxy_main.c2
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c52
4 files changed, 187 insertions, 2 deletions
diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am
index 049d41ddd..87dbc3059 100644
--- a/openbsc/src/gprs/Makefile.am
+++ b/openbsc/src/gprs/Makefile.am
@@ -13,7 +13,8 @@ else
bin_PROGRAMS = osmo-gbproxy
endif
-osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c
+osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \
+ gprs_llc_parse.c crc24.c
osmo_gbproxy_LDADD = $(top_builddir)/src/libcommon/libcommon.a \
$(OSMO_LIBS)
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 9de2ca9c4..82e9e8c70 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -43,6 +43,10 @@
#include <openbsc/debug.h>
#include <openbsc/gb_proxy.h>
+#include <openbsc/gprs_llc.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/gsm_04_08_gprs.h>
+
enum gbprox_global_ctr {
GBPROX_GLOB_CTR_INV_BVCI,
GBPROX_GLOB_CTR_INV_LAI,
@@ -55,6 +59,9 @@ enum gbprox_global_ctr {
GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
GBPROX_GLOB_CTR_TX_ERR_SGSN,
GBPROX_GLOB_CTR_OTHER_ERR,
+ GBPROX_GLOB_CTR_RAID_PATCHED_BSS,
+ GBPROX_GLOB_CTR_RAID_PATCHED_SGSN,
+ GBPROX_GLOB_CTR_PATCH_ERR,
};
static const struct rate_ctr_desc global_ctr_description[] = {
@@ -69,6 +76,9 @@ static const struct rate_ctr_desc global_ctr_description[] = {
{ "restart.sgsn", "Restarted RESET procedure (SGSN)" },
{ "tx-err.sgsn", "NS Transmission error (SGSN)" },
{ "error", "Other error " },
+ { "raid-mod.bss", "RAID patched (BSS )" },
+ { "raid-mod.sgsn", "RAID patched (SGSN)" },
+ { "mod-err", "Patching error " },
};
static const struct rate_ctr_group_desc global_ctrg_desc = {
@@ -112,6 +122,11 @@ static const struct rate_ctr_group_desc peer_ctrg_desc = {
.ctr_desc = peer_ctr_description,
};
+static struct gbprox_patch_state {
+ int local_mnc;
+ int local_mcc;
+} gbprox_patch_state = {0};
+
struct gbprox_peer {
struct llist_head list;
@@ -260,6 +275,118 @@ static void strip_ns_hdr(struct msgb *msg)
msgb_pull(msg, strip_len);
}
+/* patch RA identifier in place, update peer accordingly */
+static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *state,
+ int to_bss, const char *log_text)
+{
+ const int old_local_mcc = state->local_mcc;
+ const int old_local_mnc = state->local_mnc;
+ int old_mcc;
+ int old_mnc;
+ struct gprs_ra_id raid;
+
+ gsm48_parse_ra(&raid, raid_enc);
+
+ old_mcc = raid.mcc;
+ old_mnc = raid.mnc;
+
+ if (!to_bss) {
+ /* BSS -> SGSN */
+ /* save BSS side MCC/MNC */
+ if (!gbcfg.core_mcc || raid.mcc == gbcfg.core_mcc) {
+ state->local_mcc = 0;
+ } else {
+ state->local_mcc = raid.mcc;
+ raid.mcc = gbcfg.core_mcc;
+ }
+
+ if (!gbcfg.core_mnc || raid.mnc == gbcfg.core_mnc) {
+ state->local_mnc = 0;
+ } else {
+ state->local_mnc = raid.mnc;
+ raid.mnc = gbcfg.core_mnc;
+ }
+ } else {
+ /* SGSN -> BSS */
+ if (state->local_mcc)
+ raid.mcc = state->local_mcc;
+
+ if (state->local_mnc)
+ raid.mnc = state->local_mnc;
+ }
+
+ if (old_local_mcc != state->local_mcc ||
+ old_local_mnc != state->local_mnc)
+ LOGP(DGPRS, LOGL_NOTICE,
+ "Patching RAID %sactivated, msg: %s, "
+ "local: %d-%d, core: %d-%d, to %s\n",
+ state->local_mcc || state->local_mnc ?
+ "" : "de",
+ log_text,
+ state->local_mcc, state->local_mnc,
+ gbcfg.core_mcc, gbcfg.core_mnc,
+ to_bss ? "BSS" : "SGSN");
+
+ if (state->local_mcc || state->local_mnc) {
+ enum gbprox_global_ctr counter =
+ to_bss ?
+ GBPROX_GLOB_CTR_RAID_PATCHED_SGSN :
+ GBPROX_GLOB_CTR_RAID_PATCHED_BSS;
+
+ LOGP(DGPRS, LOGL_DEBUG,
+ "Patching %s to %s: "
+ "%d-%d-%d-%d -> %d-%d-%d-%d\n",
+ log_text,
+ to_bss ? "BSS" : "SGSN",
+ old_mcc, old_mnc, raid.lac, raid.rac,
+ raid.mcc, raid.mnc, raid.lac, raid.rac);
+
+ gsm48_construct_ra(raid_enc, &raid);
+ rate_ctr_inc(&get_global_ctrg()->ctr[counter]);
+ }
+}
+
+/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
+static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss)
+{
+ struct bssgp_normal_hdr *bgph;
+ struct bssgp_ud_hdr *budh;
+ struct tlv_parsed tp;
+ uint8_t pdu_type;
+ struct gbprox_patch_state *state = &gbprox_patch_state;
+ uint8_t *data;
+ size_t data_len;
+
+ if (!gbcfg.core_mcc && !gbcfg.core_mnc)
+ return;
+
+ bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg);
+ pdu_type = bgph->pdu_type;
+
+ if (to_bss && !state->local_mcc && !state->local_mnc)
+ return;
+
+ if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
+ pdu_type == BSSGP_PDUT_DL_UNITDATA) {
+ data = budh->data;
+ data_len = msgb_bssgp_len(msg) - sizeof(*budh);
+ } else {
+ data = bgph->data;
+ data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
+ }
+
+ bssgp_tlv_parse(&tp, data, data_len);
+
+ if (TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA))
+ gbprox_patch_raid((uint8_t *)TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA),
+ state, to_bss, "ROUTING_AREA");
+
+ if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID))
+ gbprox_patch_raid((uint8_t *)TLVP_VAL(&tp, BSSGP_IE_CELL_ID),
+ state, to_bss, "CELL_ID");
+}
+
/* feed a message down the NS-VC associated with the specified peer */
static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
{
@@ -276,6 +403,8 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
strip_ns_hdr(msg);
+ gbprox_patch_bssgp_message(msg, 0);
+
rc = gprs_ns_sendmsg(bssgp_nsi, msg);
if (rc < 0)
rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]);
@@ -679,6 +808,9 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns
struct gbprox_peer *peer;
int remote_end_is_sgsn = nsei == gbcfg.nsip_sgsn_nsei;
+ if (remote_end_is_sgsn)
+ gbprox_patch_bssgp_message(msg, 1);
+
/* Only BVCI=0 messages need special treatment */
if (ns_bvci == 0 || ns_bvci == 1) {
if (remote_end_is_sgsn)
diff --git a/openbsc/src/gprs/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c
index ff2e14b5c..1f140d48d 100644
--- a/openbsc/src/gprs/gb_proxy_main.c
+++ b/openbsc/src/gprs/gb_proxy_main.c
@@ -66,7 +66,7 @@ const char *openbsc_copyright =
"There is NO WARRANTY, to the extent permitted by law.\r\n";
static char *config_file = "osmo_gbproxy.cfg";
-struct gbproxy_config gbcfg;
+struct gbproxy_config gbcfg = {0};
static int daemonize = 0;
/* Pointer to the SGSN peer */
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index 2de0d3bc5..04431f0e3 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -51,6 +51,13 @@ static int config_write_gbproxy(struct vty *vty)
vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
VTY_NEWLINE);
+ if (g_cfg->core_mcc > 0)
+ vty_out(vty, " core-mobile-country-code %d%s",
+ g_cfg->core_mcc, VTY_NEWLINE);
+ if (g_cfg->core_mnc > 0)
+ vty_out(vty, " core-mobile-network-code %d%s",
+ g_cfg->core_mnc, VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -76,6 +83,47 @@ DEFUN(cfg_nsip_sgsn_nsei,
return CMD_SUCCESS;
}
+#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
+
+DEFUN(cfg_gbproxy_core_mnc,
+ cfg_gbproxy_core_mnc_cmd,
+ "core-mobile-network-code <1-999>",
+ GBPROXY_CORE_MNC_STR "NCC value\n")
+{
+ g_cfg->core_mnc = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_gbproxy_no_core_mnc,
+ cfg_gbproxy_no_core_mnc_cmd,
+ "no core-mobile-network-code",
+ NO_STR GBPROXY_CORE_MNC_STR)
+{
+ g_cfg->core_mnc = 0;
+ return CMD_SUCCESS;
+}
+
+#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
+
+DEFUN(cfg_gbproxy_core_mcc,
+ cfg_gbproxy_core_mcc_cmd,
+ "core-mobile-country-code <1-999>",
+ GBPROXY_CORE_MCC_STR "MCC value\n")
+{
+ g_cfg->core_mcc = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_gbproxy_no_core_mcc,
+ cfg_gbproxy_no_core_mcc_cmd,
+ "no core-mobile-country-code",
+ NO_STR GBPROXY_CORE_MCC_STR)
+{
+ g_cfg->core_mcc = 0;
+ return CMD_SUCCESS;
+}
+
+
int gbproxy_vty_init(void)
{
install_element_ve(&show_gbproxy_cmd);
@@ -87,6 +135,10 @@ int gbproxy_vty_init(void)
install_node(&gbproxy_node, config_write_gbproxy);
vty_install_default(GBPROXY_NODE);
install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
return 0;
}