bsc: Allow to use different LAC/CI for the core-network

We need to use different LAC/CI towards the core network.
It is a bit problematic as LAC/CI is a per BTS attribute
so this feature only works if a BSC manages everything in
the same LAC.

Related: SYS#1398
diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h
index add561c..bdc762a 100644
--- a/openbsc/include/openbsc/osmo_msc_data.h
+++ b/openbsc/include/openbsc/osmo_msc_data.h
@@ -1,8 +1,8 @@
 /*
  * Data for the true BSC
  *
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 by On-Waves
+ * (C) 2010-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2015 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -67,6 +67,8 @@
 	struct bsc_msc_connection *msc_con;
 	int core_ncc;
 	int core_mcc;
+	int core_lac;
+	int core_ci;
 	int rtp_base;
 
 	/* audio codecs */
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index 2c661b3..18b9607 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -65,6 +65,21 @@
 	return msc->network->country_code;
 }
 
+static uint16_t get_lac_for_msc(struct osmo_msc_data *msc, struct gsm_bts *bts)
+{
+	if (msc->core_lac != -1)
+		return msc->core_lac;
+	return bts->location_area_code;
+}
+
+static uint16_t get_ci_for_msc(struct osmo_msc_data *msc, struct gsm_bts *bts)
+{
+	if (msc->core_ci != -1)
+		return msc->core_ci;
+	return bts->cell_identity;
+}
+
+
 static void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
 {
 	struct msgb *resp;
@@ -161,6 +176,8 @@
 	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;
 
@@ -189,11 +206,11 @@
 
 	network_code = get_network_code_for_msc(conn->sccp_con->msc);
 	country_code = get_country_code_for_msc(conn->sccp_con->msc);
+	lac = get_lac_for_msc(conn->sccp_con->msc, conn->bts);
+	ci = get_ci_for_msc(conn->sccp_con->msc, conn->bts);
 
 	bsc_scan_bts_msg(conn, msg);
-	resp = gsm0808_create_layer3(msg, network_code, country_code,
-				     conn->bts->location_area_code,
-				     conn->bts->cell_identity);
+	resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci);
 	if (!resp) {
 		LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
 		sccp_connection_free(conn->sccp_con->sccp);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
index 596bfbd..58a57cd 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
@@ -311,6 +311,19 @@
 	return 0;
 }
 
+static int has_core_identity(struct osmo_msc_data *msc)
+{
+	if (msc->core_ncc != -1)
+		return 1;
+	if (msc->core_mcc != -1)
+		return 1;
+	if (msc->core_lac != -1)
+		return 1;
+	if (msc->core_ci != -1)
+		return 1;
+	return 0;
+}
+
 /**
  * Messages coming back from the MSC.
  */
@@ -336,7 +349,7 @@
 	msc = conn->sccp_con->msc;
 
 	if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
-		if (msc->core_ncc != -1 || msc->core_mcc != -1) {
+		if (has_core_identity(msc)) {
 			if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
 				lai = (struct gsm48_loc_area_id *) &gh->data[0];
 				gsm48_generate_lai(lai, net->country_code,
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index e762cdd..d3507d5 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -1,8 +1,8 @@
 /*
  * Handle the connection to the MSC. This include ping/timeout/reconnect
  * (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2014 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2014 by On-Waves
+ * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2015 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -524,6 +524,8 @@
 	msc_data->pong_timeout = 5;
 	msc_data->core_ncc = -1;
 	msc_data->core_mcc = -1;
+	msc_data->core_ci = -1;
+	msc_data->core_lac = -1;
 	msc_data->rtp_base = 4000;
 
 	msc_data->nr = nr;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index ab36e47..bbbba1c 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -112,6 +112,12 @@
 	if (msc->core_mcc != -1)
 		vty_out(vty, " core-mobile-country-code %d%s",
 			msc->core_mcc, VTY_NEWLINE);
+	if (msc->core_lac != -1)
+		vty_out(vty, " core-location-area-code %d%s",
+			msc->core_lac, VTY_NEWLINE);
+	if (msc->core_ci != -1)
+		vty_out(vty, " core-cell-identity %d%s",
+			msc->core_ci, VTY_NEWLINE);
 	vty_out(vty, " ip.access rtp-base %d%s", msc->rtp_base, VTY_NEWLINE);
 
 	if (msc->ping_timeout == -1)
@@ -239,6 +245,26 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_net_bsc_lac,
+      cfg_net_bsc_lac_cmd,
+      "core-location-area-code <0-65535>",
+      "Use this location area code for the core network\n" "LAC value\n")
+{
+	struct osmo_msc_data *data = osmo_msc_data(vty);
+	data->core_lac = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_bsc_ci,
+      cfg_net_bsc_ci_cmd,
+      "core-cell-identity <0-65535>",
+      "Use this cell identity for the core network\n" "CI value\n")
+{
+	struct osmo_msc_data *data = osmo_msc_data(vty);
+	data->core_ci = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_net_bsc_rtp_base,
       cfg_net_bsc_rtp_base_cmd,
       "ip.access rtp-base <1-65000>",
@@ -785,6 +811,8 @@
 	install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_mcc_cmd);
+	install_element(MSC_NODE, &cfg_net_bsc_lac_cmd);
+	install_element(MSC_NODE, &cfg_net_bsc_ci_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_rtp_base_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_codec_list_cmd);
 	install_element(MSC_NODE, &cfg_net_msc_dest_cmd);
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 9a531cf..2b7fd19 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -495,6 +495,21 @@
         self.assert_(res.find(" timeout-pong 14") > 0)
         self.assert_(res.find(" timeout-ping advanced") > 0)
 
+    def testMscDataCoreLACCI(self):
+        self.vty.enable()
+        res = self.vty.command("show running-config")
+        self.assertEquals(res.find("core-location-area-code"), -1)
+        self.assertEquals(res.find("core-cell-identity"), -1)
+
+	self.vty.command("configure terminal")
+        self.vty.command("msc 0")
+        self.vty.command("core-location-area-code 666")
+        self.vty.command("core-cell-identity 333")
+
+        res = self.vty.command("show running-config")
+        self.assert_(res.find("core-location-area-code 666") > 0)
+        self.assert_(res.find("core-cell-identity 333") > 0)
+
 class TestVTYNAT(TestVTYGenericBSC):
 
     def vty_command(self):