aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2018-03-05 02:09:40 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2018-03-07 15:34:48 +0000
commitf93970b167aba2805cc67e1326591f31fbe93ada (patch)
treefefb1abf602475204e443563b634596df9ff5444 /src/osmo-bsc
parent56dec0c75358fe42954f9e7949ebd0c163377b10 (diff)
implement support for 3-digit MNC with leading zeros
Add 3-digit flags and use the new RAI and LAI API from libosmocore throughout the code base to be able to handle an MNC < 100 that has three digits (leading zeros). The changes to abis_test and gsm0408_test show that this code now handles 3-digit MNC correctly, by not dropping the leading zero as 0xf in the encoded PLMN. Re-implement CTRL commands 'mcc', 'mnc' and 'mcc-mnc-apply' to preserve the presence of the third digit of the MNC. Always reply with all leading zeros. Adjust the expected results in ctrl_test_runner.py, to show that it works. In VTY and CTRL, the parsing of MCC and MNC is inherently made stricter by use of osmo_{mcc,mnc}_from_str() -- they will no longer allow surplus characters and detect errno returned by strtol() (in contrast to atoi()). Depends: Id2240f7f518494c9df6c8bda52c0d5092f90f221 (libosmocore), Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 (libosmocore), I020a4f11791c61742a3d795f782805f7b7e8733e (libosmocore) Change-Id: I8e722103344186fde118b26d8353db95a4581daa
Diffstat (limited to 'src/osmo-bsc')
-rw-r--r--src/osmo-bsc/osmo_bsc_api.c47
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c58
-rw-r--r--src/osmo-bsc/osmo_bsc_ctrl.c7
-rw-r--r--src/osmo-bsc/osmo_bsc_filter.c18
-rw-r--r--src/osmo-bsc/osmo_bsc_msc.c6
-rw-r--r--src/osmo-bsc/osmo_bsc_vty.c30
6 files changed, 71 insertions, 95 deletions
diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c
index 465832c82..75dae1293 100644
--- a/src/osmo-bsc/osmo_bsc_api.c
+++ b/src/osmo-bsc/osmo_bsc_api.c
@@ -54,32 +54,20 @@ static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca
static int complete_layer3(struct gsm_subscriber_connection *conn,
struct msgb *msg, struct bsc_msc_data *msc);
-static uint16_t get_network_code_for_msc(struct bsc_msc_data *msc)
+static struct osmo_cell_global_id *cgi_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
{
- if (msc->core_mnc != -1)
- return msc->core_mnc;
- return msc->network->network_code;
-}
-
-static uint16_t get_country_code_for_msc(struct bsc_msc_data *msc)
-{
- if (msc->core_mcc != -1)
- return msc->core_mcc;
- return msc->network->country_code;
-}
-
-static uint16_t get_lac_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
-{
- if (msc->core_lac != -1)
- return msc->core_lac;
- return bts->location_area_code;
-}
+ static struct osmo_cell_global_id cgi;
+ cgi.lai.plmn = msc->network->plmn;
+ if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
+ cgi.lai.plmn.mcc = msc->core_plmn.mcc;
+ if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID) {
+ cgi.lai.plmn.mnc = msc->core_plmn.mnc;
+ cgi.lai.plmn.mnc_3_digits = msc->core_plmn.mnc_3_digits;
+ }
+ cgi.lai.lac = (msc->core_lac != -1) ? msc->core_lac : bts->location_area_code;
+ cgi.cell_identity = (msc->core_ci != -1) ? msc->core_ci : bts->cell_identity;
-static uint16_t get_ci_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
-{
- if (msc->core_ci != -1)
- return msc->core_ci;
- return bts->cell_identity;
+ return &cgi;
}
static void bsc_maybe_lu_reject(struct gsm_subscriber_connection *conn, int con_type, int cause)
@@ -242,10 +230,6 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
char *imsi = NULL;
struct timeval tv;
struct msgb *resp;
- uint16_t network_code;
- uint16_t country_code;
- uint16_t lac;
- uint16_t ci;
enum bsc_con ret;
int send_ping = msc->advanced_ping;
@@ -285,14 +269,9 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
/* check return value, if failed check msg for and send USSD */
- network_code = get_network_code_for_msc(conn->sccp.msc);
- country_code = get_country_code_for_msc(conn->sccp.msc);
- lac = get_lac_for_msc(conn->sccp.msc, conn_get_bts(conn));
- ci = get_ci_for_msc(conn->sccp.msc, conn_get_bts(conn));
-
bsc_scan_bts_msg(conn, msg);
- resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci);
+ resp = gsm0808_create_layer3_2(msg, cgi_for_msc(conn->sccp.msc, conn_get_bts(conn)), NULL);
if (!resp) {
LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
osmo_bsc_sigtran_del_conn(conn);
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index d07cc558e..db749a3da 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -262,15 +262,14 @@ page_subscriber(struct bsc_msc_data *msc, struct gsm_bts *bts,
/* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC.
* Return 0 if successful, negative on error. */
-static int
-decode_lai(const uint8_t *data, uint16_t *mcc, uint16_t *mnc, uint16_t *lac)
+static void
+decode_lai(const uint8_t *data, struct osmo_location_area_id *laid)
{
struct gsm48_loc_area_id lai;
/* Copy data to stack to prevent unaligned access in gsm48_decode_lai(). */
memcpy(&lai, data, sizeof(lai)); /* don't byte swap yet */
-
- return gsm48_decode_lai(&lai, mcc, mnc, lac) != 0 ? -1 : 0;
+ gsm48_decode_lai2(&lai, laid);
}
static void
@@ -290,37 +289,33 @@ page_cgi(struct bsc_msc_data *msc, const uint8_t *data, uint8_t data_length, siz
uint16_t ci;
int i = 0;
while (remain >= sizeof(struct gsm48_loc_area_id) + sizeof(ci)) {
- uint16_t mcc, mnc, lac, *ci_be;
+ struct osmo_location_area_id lai;
+ uint16_t *ci_be;
size_t lai_offset = 1 + i * (sizeof(struct gsm48_loc_area_id) + sizeof(ci));
- if (decode_lai(&data[lai_offset], &mcc, &mnc, &lac) != 0) {
- LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List "
- "for BSS (0x%x), paging entire BSS anyway (%s)\n",
- mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length));
- page_all_bts(msc, tmsi, mi_string, chan_needed);
- return;
- }
+ decode_lai(&data[lai_offset], &lai);
ci_be = (uint16_t *)(&data[lai_offset + sizeof(struct gsm48_loc_area_id)]);
ci = osmo_load16be(ci_be);
- if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
+ if (!osmo_plmn_cmp(&lai.plmn, &msc->network->plmn)) {
int paged = 0;
struct gsm_bts *bts;
llist_for_each_entry(bts, &msc->network->bts_list, list) {
- if (bts->location_area_code != lac)
+ if (bts->location_area_code != lai.lac)
continue;
if (bts->cell_identity != ci)
continue;
/* ignore errors from page_subscriber(); keep trying other BTS */
- page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed);
+ page_subscriber(msc, bts, tmsi, lai.lac, mi_string, chan_needed);
paged = 1;
}
if (!paged) {
LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: BTS with LAC %d and CI %d not found\n",
- mi_string, lac, ci);
+ mi_string, lai.lac, ci);
}
} else {
- LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC/MNC in Cell Identifier List "
- "(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc,
- msc->network->country_code, msc->network->network_code);
+ LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC-MNC in Cell Identifier List "
+ "(%s) do not match our network (%s)\n",
+ mi_string, osmo_plmn_name(&lai.plmn),
+ osmo_plmn_name2(&msc->network->plmn));
}
remain -= sizeof(struct gsm48_loc_area_id) + sizeof(ci);
i++;
@@ -389,32 +384,27 @@ page_lai_and_lac(struct bsc_msc_data *msc, const uint8_t *data, size_t data_leng
{
int i = 0;
while (remain >= sizeof(struct gsm48_loc_area_id)) {
- uint16_t mcc, mnc, lac;
- if (decode_lai(&data[1 + i * sizeof(struct gsm48_loc_area_id)], &mcc, &mnc, &lac) != 0) {
- LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List "
- "for BSS (0x%x), paging entire BSS anyway (%s)\n",
- mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length));
- page_all_bts(msc, tmsi, mi_string, chan_needed);
- return;
- }
- if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
+ struct osmo_location_area_id lai;
+ decode_lai(&data[1 + i * sizeof(struct gsm48_loc_area_id)], &lai);
+ if (!osmo_plmn_cmp(&lai.plmn, &msc->network->plmn)) {
int paged = 0;
struct gsm_bts *bts;
llist_for_each_entry(bts, &msc->network->bts_list, list) {
- if (bts->location_area_code != lac)
+ if (bts->location_area_code != lai.lac)
continue;
/* ignore errors from page_subscriber(); keep trying other BTS */
- page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed);
+ page_subscriber(msc, bts, tmsi, lai.lac, mi_string, chan_needed);
paged = 1;
}
if (!paged) {
LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: BTS with LAC %d not found\n",
- mi_string, lac);
+ mi_string, lai.lac);
}
} else {
- LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC/MNC in Cell Identifier List "
- "(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc,
- msc->network->country_code, msc->network->network_code);
+ LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC-MNC in Cell Identifier List "
+ "(%s) do not match our network (%s)\n",
+ mi_string, osmo_plmn_name(&lai.plmn),
+ osmo_plmn_name2(&msc->network->plmn));
}
remain -= sizeof(struct gsm48_loc_area_id);
i++;
diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c
index 6092f2379..5f88b85f7 100644
--- a/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -207,10 +207,11 @@ static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_con
policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
cmd->reply = talloc_asprintf_append(cmd->reply,
- ",%s,%s,%s,%d,%d",
+ ",%s,%s,%s,%s,%s",
oper, admin, policy,
- bts->network->country_code,
- bts->network->network_code);
+ osmo_mcc_name(bts->network->plmn.mcc),
+ osmo_mnc_name(bts->network->plmn.mnc,
+ bts->network->plmn.mnc_3_digits));
osmo_bsc_send_trap(cmd, msc_con);
talloc_free(cmd);
diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c
index c1f3e80a6..5f60989a7 100644
--- a/src/osmo-bsc/osmo_bsc_filter.c
+++ b/src/osmo-bsc/osmo_bsc_filter.c
@@ -36,21 +36,16 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn,
struct gsm48_hdr *gh;
struct gsm48_loc_upd_req *lu;
struct gsm48_loc_area_id lai;
- struct gsm_network *net;
- struct gsm_bts *bts = conn_get_bts(conn);
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
return;
}
- net = bts->network;
-
gh = msgb_l3(msg);
lu = (struct gsm48_loc_upd_req *) gh->data;
- gsm48_generate_lai(&lai, net->country_code, net->network_code,
- bts->location_area_code);
+ gsm48_generate_lai2(&lai, bts_lai(conn_get_bts(conn)));
if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
@@ -315,9 +310,9 @@ static int bsc_patch_mm_info(struct gsm_subscriber_connection *conn,
static int has_core_identity(struct bsc_msc_data *msc)
{
- if (msc->core_mnc != -1)
+ if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID)
return 1;
- if (msc->core_mcc != -1)
+ if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
return 1;
if (msc->core_lac != -1)
return 1;
@@ -332,8 +327,6 @@ static int has_core_identity(struct bsc_msc_data *msc)
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
struct bsc_msc_data *msc;
- struct gsm_bts *bts = conn_get_bts(conn);
- struct gsm_network *net;
struct gsm48_loc_area_id *lai;
struct gsm48_hdr *gh;
uint8_t pdisc;
@@ -353,7 +346,6 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
return 0;
mtype = gsm48_hdr_msg_type(gh);
- net = bts->network;
msc = conn->sccp.msc;
if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
@@ -361,9 +353,7 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
/* overwrite LAI in the message */
lai = (struct gsm48_loc_area_id *) &gh->data[0];
- gsm48_generate_lai(lai, net->country_code,
- net->network_code,
- bts->location_area_code);
+ gsm48_generate_lai2(lai, bts_lai(conn_get_bts(conn)));
}
}
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index 46be2e644..e0c7556a9 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -581,8 +581,10 @@ struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
INIT_LLIST_HEAD(&msc_data->dests);
msc_data->ping_timeout = 20;
msc_data->pong_timeout = 5;
- msc_data->core_mnc = -1;
- msc_data->core_mcc = -1;
+ msc_data->core_plmn = (struct osmo_plmn_id){
+ .mcc = GSM_MCC_MNC_INVALID,
+ .mnc = GSM_MCC_MNC_INVALID,
+ };
msc_data->core_ci = -1;
msc_data->core_lac = -1;
msc_data->rtp_base = 4000;
diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c
index e173b4a7b..3455d01af 100644
--- a/src/osmo-bsc/osmo_bsc_vty.c
+++ b/src/osmo-bsc/osmo_bsc_vty.c
@@ -27,6 +27,7 @@
#include <osmocom/bsc/bsc_msg_filter.h>
#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm48.h>
#include <osmocom/vty/logging.h>
#include <osmocom/mgcp_client/mgcp_client.h>
@@ -107,12 +108,12 @@ static void write_msc(struct vty *vty, struct bsc_msc_data *msc)
struct bsc_msc_dest *dest;
vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE);
- if (msc->core_mnc != -1)
- vty_out(vty, " core-mobile-network-code %d%s",
- msc->core_mnc, VTY_NEWLINE);
- if (msc->core_mcc != -1)
- vty_out(vty, " core-mobile-country-code %d%s",
- msc->core_mcc, VTY_NEWLINE);
+ if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID)
+ vty_out(vty, " core-mobile-network-code %s%s",
+ osmo_mnc_name(msc->core_plmn.mnc, msc->core_plmn.mnc_3_digits), VTY_NEWLINE);
+ if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
+ vty_out(vty, " core-mobile-country-code %s%s",
+ osmo_mcc_name(msc->core_plmn.mcc), VTY_NEWLINE);
if (msc->core_lac != -1)
vty_out(vty, " core-location-area-code %d%s",
msc->core_lac, VTY_NEWLINE);
@@ -236,7 +237,15 @@ DEFUN(cfg_net_bsc_ncc,
"Use this network code for the core network\n" "MNC value\n")
{
struct bsc_msc_data *data = bsc_msc_data(vty);
- data->core_mnc = atoi(argv[0]);
+ uint16_t mnc;
+ bool mnc_3_digits;
+
+ if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
+ vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ data->core_plmn.mnc = mnc;
+ data->core_plmn.mnc_3_digits = mnc_3_digits;
return CMD_SUCCESS;
}
@@ -245,8 +254,13 @@ DEFUN(cfg_net_bsc_mcc,
"core-mobile-country-code <1-999>",
"Use this country code for the core network\n" "MCC value\n")
{
+ uint16_t mcc;
struct bsc_msc_data *data = bsc_msc_data(vty);
- data->core_mcc = atoi(argv[0]);
+ if (osmo_mcc_from_str(argv[0], &mcc)) {
+ vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ data->core_plmn.mcc = mcc;
return CMD_SUCCESS;
}