nanobts: Fix initialization of two concurrent BTS.

It was possible that the wrong NSEI information was sent to the
BTS. This is because patch_nm_tables is not called before sending
the data to the BTS. This will break when two BTS connect more or
less at the same time.

Stop using the arrays directly and instead introduce a method
that will patch the table and return the data and length. This
makes sure that all users patch the table before we send the
data to the BTS.

I bootstrapped a sysmoBTS and I can bring up rsl. The device is
running with a dummy load so I couldn't do more verification.
diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts.c b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
index c8b235d..dfc8d16 100644
--- a/openbsc/src/libbsc/bts_ipaccess_nanobts.c
+++ b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
@@ -265,6 +265,40 @@
 	}
 }
 
+static uint8_t *nanobts_attr_bts_get(struct gsm_bts *bts, size_t *data_len)
+{
+	patch_nm_tables(bts);
+	*data_len = sizeof(nanobts_attr_bts);
+	return nanobts_attr_bts;
+}
+
+static uint8_t *nanobts_attr_nse_get(struct gsm_bts *bts, size_t *data_len)
+{
+	patch_nm_tables(bts);
+	*data_len = sizeof(nanobts_attr_nse);
+	return nanobts_attr_nse;
+}
+
+static uint8_t *nanobts_attr_cell_get(struct gsm_bts *bts, size_t *data_len)
+{
+	patch_nm_tables(bts);
+	*data_len = sizeof(nanobts_attr_cell);
+	return nanobts_attr_cell;
+}
+
+static uint8_t *nanobts_attr_nscv_get(struct gsm_bts *bts, size_t *data_len)
+{
+	patch_nm_tables(bts);
+	*data_len = sizeof(nanobts_attr_nsvc0);
+	return nanobts_attr_nsvc0;
+}
+
+static uint8_t *nanobts_attr_radio_get(struct gsm_bts *bts, size_t *data_len)
+{
+	patch_nm_tables(bts);
+	*data_len = sizeof(nanobts_attr_radio);
+	return nanobts_attr_radio;
+}
 
 /* Callback function to be called whenever we get a GSM 12.21 state change event */
 static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
@@ -278,6 +312,9 @@
 	struct gsm_bts_trx_ts *ts;
 	struct gsm_bts_gprs_nsvc *nsvc;
 
+	uint8_t *data;
+	size_t data_len;
+
 	if (!is_ipaccess_bts(nsd->bts))
 		return 0;
 
@@ -300,9 +337,8 @@
 	case NM_OC_BTS:
 		bts = obj;
 		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
-			patch_nm_tables(bts);
-			abis_nm_set_bts_attr(bts, nanobts_attr_bts,
-					     sizeof(nanobts_attr_bts));
+			data = nanobts_attr_bts_get(bts, &data_len);
+			abis_nm_set_bts_attr(bts, data, data_len);
 			abis_nm_chg_adm_state(bts, obj_class,
 					      bts->bts_nr, 0xff, 0xff,
 					      NM_STATE_UNLOCKED);
@@ -315,7 +351,6 @@
 		trx = ts->trx;
 		if (new_state->operational == NM_OPSTATE_DISABLED &&
 		    new_state->availability == NM_AVSTATE_DEPENDENCY) {
-			patch_nm_tables(trx->bts);
 			enum abis_nm_chan_comb ccomb =
 						abis_nm_chcomb4pchan(ts->pchan);
 			abis_nm_set_channel_attr(ts, ccomb);
@@ -338,9 +373,9 @@
 		if (bts->gprs.mode == BTS_GPRS_NONE)
 			break;
 		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
+			data = nanobts_attr_nse_get(bts, &data_len);
 			abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
-						  0xff, 0xff, nanobts_attr_nse,
-						  sizeof(nanobts_attr_nse));
+						  0xff, 0xff, data, data_len);
 			abis_nm_opstart(bts, obj_class, bts->bts_nr,
 					0xff, 0xff);
 		}
@@ -350,9 +385,9 @@
 		if (bts->gprs.mode == BTS_GPRS_NONE)
 			break;
 		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
+			data = nanobts_attr_cell_get(bts, &data_len);
 			abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
-						  0, 0xff, nanobts_attr_cell,
-						  sizeof(nanobts_attr_cell));
+						  0, 0xff, data, data_len);
 			abis_nm_opstart(bts, obj_class, bts->bts_nr,
 					0, 0xff);
 			abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
@@ -371,10 +406,10 @@
 			break;
 		if ((new_state->availability == NM_AVSTATE_OFF_LINE) ||
 		    (new_state->availability == NM_AVSTATE_DEPENDENCY)) {
+			data = nanobts_attr_nscv_get(bts, &data_len);
 			abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
 						  nsvc->id, 0xff,
-						  nanobts_attr_nsvc0,
-						  sizeof(nanobts_attr_nsvc0));
+						  data, data_len);
 			abis_nm_opstart(bts, obj_class, bts->bts_nr,
 					nsvc->id, 0xff);
 			abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
@@ -424,11 +459,12 @@
 		 */
 		int rc_state = trx->mo.nm_state.administrative;
 		/* Patch ARFCN into radio attribute */
-		nanobts_attr_radio[5] &= 0xf0;
-		nanobts_attr_radio[5] |= trx->arfcn >> 8;
-		nanobts_attr_radio[6] = trx->arfcn & 0xff;
-		abis_nm_set_radio_attr(trx, nanobts_attr_radio,
-				       sizeof(nanobts_attr_radio));
+		size_t data_len;
+		uint8_t *data = nanobts_attr_radio_get(trx->bts, &data_len);
+		data[5] &= 0xf0;
+		data[5] |= trx->arfcn >> 8;
+		data[6] = trx->arfcn & 0xff;
+		abis_nm_set_radio_attr(trx, data, data_len);
 		abis_nm_chg_adm_state(trx->bts, foh->obj_class,
 				      trx->bts->bts_nr, trx->nr, 0xff,
 				      rc_state);