the actual config file code (not just config files)

this was missing from commit a08a9acdb6bff0ee4fdf0f58b78b6525017a1f9f
diff --git a/openbsc/include/openbsc/e1_input.h b/openbsc/include/openbsc/e1_input.h
index 1326723..1e8da56 100644
--- a/openbsc/include/openbsc/e1_input.h
+++ b/openbsc/include/openbsc/e1_input.h
@@ -113,6 +113,9 @@
 /* register a line with the E1 core */
 int e1inp_line_register(struct e1inp_line *line);
 
+/* ensure a certain line exists, return pointer to it */
+struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr);
+
 /* find a sign_link for given TEI and SAPI in a TS */
 struct e1inp_sign_link *
 e1inp_lookup_sign_link(struct e1inp_ts *ts, u_int8_t tei,
@@ -148,8 +151,12 @@
 /* called by TRAU muxer to obtain the destination mux entity */
 struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr);
 
+
 /* e1_config.c */
-int e1_config(struct gsm_bts *bts, int cardnr, int release_l2);
+int e1_reconfig_ts(struct gsm_bts_trx_ts *ts);
+int e1_reconfig_trx(struct gsm_bts_trx *trx);
+int e1_reconfig_bts(struct gsm_bts *bts);
+
 int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin);
 int ipaccess_setup(struct gsm_network *gsmnet);
 
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 663c869..8af0781 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -200,7 +200,10 @@
 	/* number of this TRX in the BTS */
 	u_int8_t nr;
 	/* how do we talk RSL with this TRX? */
+	struct gsm_e1_subslot rsl_e1_link;
+	u_int8_t rsl_tei;
 	struct e1inp_sign_link *rsl_link;
+
 	struct gsm_nm_state nm_state;
 	struct tlv_parsed nm_attr;
 	struct {
@@ -293,6 +296,8 @@
 	enum gsm_bts_type type;
 	enum gsm_band band;
 	/* how do we talk OML with this TRX? */
+	struct gsm_e1_subslot oml_e1_link;
+	u_int8_t oml_tei;
 	struct e1inp_sign_link *oml_link;
 
 	/* Abis network management O&M handle */
@@ -404,7 +409,7 @@
 				struct gsm_bts *start_bts);
 
 char *gsm_band_name(enum gsm_band band);
-enum gsm_band gsm_band_parse(int mhz);
+enum gsm_band gsm_band_parse(const char *mhz);
 
 extern void *tall_bsc_ctx;
 
diff --git a/openbsc/include/openbsc/talloc.h b/openbsc/include/openbsc/talloc.h
index a4b33c3..f7f7643 100644
--- a/openbsc/include/openbsc/talloc.h
+++ b/openbsc/include/openbsc/talloc.h
@@ -29,6 +29,8 @@
 #include <stdio.h>
 #include <stdarg.h>
 
+#define HAVE_VA_COPY
+
 /* this is only needed for compatibility with the old talloc */
 typedef void TALLOC_CTX;
 
diff --git a/openbsc/include/vty/command.h b/openbsc/include/vty/command.h
index 1be05aa..21fb6a1 100644
--- a/openbsc/include/vty/command.h
+++ b/openbsc/include/vty/command.h
@@ -61,12 +61,6 @@
 
 /* There are some command levels which called from command node. */
 enum node_type {
-	GSMNET_NODE,
-	BTS_NODE,
-	TRX_NODE,
-	TS_NODE,
-	SUBSCR_NODE,
-
 	AUTH_NODE,		/* Authentication mode of vty interface. */
 	VIEW_NODE,		/* View node. Default mode of vty interface. */
 	AUTH_ENABLE_NODE,	/* Authentication mode for change enable. */
@@ -74,6 +68,7 @@
 	CONFIG_NODE,		/* Config node. Default mode of config file. */
 	SERVICE_NODE,		/* Service node. */
 	DEBUG_NODE,		/* Debug node. */
+#if 0
 	AAA_NODE,		/* AAA node. */
 	KEYCHAIN_NODE,		/* Key-chain node. */
 	KEYCHAIN_KEY_NODE,	/* Key-chain key node. */
@@ -103,7 +98,14 @@
 	SMUX_NODE,		/* SNMP configuration node. */
 	DUMP_NODE,		/* Packet dump node. */
 	FORWARDING_NODE,	/* IP forwarding node. */
-	VTY_NODE		/* Vty node. */
+#endif
+	VTY_NODE,		/* Vty node. */
+
+	GSMNET_NODE,
+	BTS_NODE,
+	TRX_NODE,
+	TS_NODE,
+	SUBSCR_NODE,
 };
 
 /* Node which has some commands and prompt string and configuration
diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c
index 9e0a260..0759f26 100644
--- a/openbsc/src/bsc_hack.c
+++ b/openbsc/src/bsc_hack.c
@@ -55,27 +55,12 @@
 /* MCC and MNC for the Location Area Identifier */
 static int MCC = 1;
 static int MNC = 1;
-static int LAC = 1;
-static int TSC = HARDCODED_TSC;
-static int BSIC = HARDCODED_BSIC;
-static int ARFCN = HARDCODED_ARFCN;
 static int cardnr = 0;
 static int release_l2 = 0;
-static int bs11_has_trx1 = 0;
-static int bs11_has_bts1 = 0;
 static enum gsm_bts_type BTS_TYPE = GSM_BTS_TYPE_BS11;
-static enum gsm_band BAND = GSM_BAND_900;
 static const char *database_name = "hlr.sqlite3";
 extern int ipacc_rtp_direct;
 
-struct nano_bts_id {
-	struct llist_head entry;
-	int site_id;
-	int bts_id;
-};
-
-static LLIST_HEAD(nanobts_ids);
-
 
 /* The following definitions are for OM and NM packets that we cannot yet
  * generate by code but we just pass on */
@@ -986,7 +971,8 @@
 {
 	fprintf(stdout, "bootstrapping RSL for BTS/TRX (%u/%u) "
 		"using MCC=%u MNC=%u BSIC=%u TSC=%u\n",
-		trx->bts->nr, trx->nr, MCC, MNC, BSIC, TSC);
+		trx->bts->nr, trx->nr, gsmnet->country_code, 
+		gsmnet->network_code, trx->bts->bsic, trx->bts->tsc);
 	set_system_infos(trx);
 }
 
@@ -1016,9 +1002,25 @@
 
 static int bootstrap_bts(struct gsm_bts *bts)
 {
-	bts->band = BAND;
-	bts->location_area_code = LAC;
-	bts->c0->arfcn = ARFCN;
+	switch (bts->type) {
+	case GSM_BTS_TYPE_NANOBTS_1800:
+		if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) {
+			fprintf(stderr, "GSM1800 channel must be between 512-885.\n");
+			return -EINVAL;
+		}
+		break;
+	case GSM_BTS_TYPE_BS11:
+	case GSM_BTS_TYPE_NANOBTS_900:
+		/* Assume we have a P-GSM900 here */
+		if (bts->c0->arfcn < 1 || bts->c0->arfcn > 124) {
+			fprintf(stderr, "GSM900 channel must be between 1-124.\n");
+			return -EINVAL;
+		}
+		break;
+	case GSM_BTS_TYPE_UNKNOWN:
+		fprintf(stderr, "Unknown BTS. Please specify\n");
+		return -EINVAL;
+	}
 
 	/* Control Channel Description */
 	memset(&bts->chan_desc, 0, sizeof(struct gsm48_control_channel_descr));
@@ -1031,66 +1033,21 @@
 
 	paging_init(bts);
 
-	if (bts->type == GSM_BTS_TYPE_BS11) {
-		struct gsm_bts_trx *trx = bts->c0;
-		set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
-		set_ts_e1link(&trx->ts[1], 0, 2, 1);
-		set_ts_e1link(&trx->ts[2], 0, 2, 2);
-		set_ts_e1link(&trx->ts[3], 0, 2, 3);
-		set_ts_e1link(&trx->ts[4], 0, 3, 0);
-		set_ts_e1link(&trx->ts[5], 0, 3, 1);
-		set_ts_e1link(&trx->ts[6], 0, 3, 2);
-		set_ts_e1link(&trx->ts[7], 0, 3, 3);
-
-		/* TRX 1 */
-		trx = gsm_bts_trx_num(bts, 1);
-		if (trx) {
-			trx = gsm_bts_trx_num(bts, 1);
-			set_ts_e1link(&trx->ts[0], 0, 4, 0);
-			set_ts_e1link(&trx->ts[1], 0, 4, 1);
-			set_ts_e1link(&trx->ts[2], 0, 4, 2);
-			set_ts_e1link(&trx->ts[3], 0, 4, 3);
-			set_ts_e1link(&trx->ts[4], 0, 5, 0);
-			set_ts_e1link(&trx->ts[5], 0, 5, 1);
-			set_ts_e1link(&trx->ts[6], 0, 5, 2);
-			set_ts_e1link(&trx->ts[7], 0, 5, 3);
-		}
-	}
-
 	return 0;
 }
 
 static int bootstrap_network(void)
 {
+	struct gsm_bts *bts;
 	int rc;
 
-	switch(BTS_TYPE) {
-	case GSM_BTS_TYPE_NANOBTS_1800:
-		if (ARFCN < 512 || ARFCN > 885) {
-			fprintf(stderr, "GSM1800 channel must be between 512-885.\n");
-			return -EINVAL;
-		}
-		break;
-	case GSM_BTS_TYPE_BS11:
-	case GSM_BTS_TYPE_NANOBTS_900:
-		/* Assume we have a P-GSM900 here */
-		if (ARFCN < 1 || ARFCN > 124) {
-			fprintf(stderr, "GSM900 channel must be between 1-124.\n");
-			return -EINVAL;
-		}
-		break;
-	case GSM_BTS_TYPE_UNKNOWN:
-		fprintf(stderr, "Unknown BTS. Please use the --bts-type switch\n");
-		return -EINVAL;
-	}
-
 	/* initialize our data structures */
 	gsmnet = gsm_network_init(MCC, MNC, mncc_recv);
 	if (!gsmnet)
 		return -ENOMEM;
 
-	gsmnet->name_long = "OpenBSC";
-	gsmnet->name_short = "OpenBSC";
+	gsmnet->name_long = talloc_strdup(gsmnet, "OpenBSC");
+	gsmnet->name_short = talloc_strdup(gsmnet, "OpenBSC");
 
 	if (db_init(database_name)) {
 		printf("DB: Failed to init database. Please check the option settings.\n");
@@ -1105,56 +1062,24 @@
 	printf("DB: Database prepared.\n");
 
 	telnet_init(gsmnet, 4242);
+	rc = vty_read_config_file("openbsc.cfg");
+	if (rc < 0)
+		return rc;
 
 	register_signal_handler(SS_NM, nm_sig_cb, NULL);
 
-	/* E1 mISDN input setup */
-	if (BTS_TYPE == GSM_BTS_TYPE_BS11) {
-		struct gsm_bts *bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
-
-		if (bs11_has_trx1) {
-			struct gsm_bts_trx *trx1;
-			trx1 = gsm_bts_trx_alloc(bts);
-			trx1->arfcn = ARFCN + 2;
-		}
+	llist_for_each_entry(bts, &gsmnet->bts_list, list) { 
 		bootstrap_bts(bts);
-		rc = e1_config(bts, cardnr, release_l2);
-		if (rc < 0) {
-			fprintf(stderr, "Error during E1 config of BTS 0\n");
-			return rc;
-		}
+		if (is_ipaccess_bts(bts))
+			rc = ipaccess_setup(bts);
+		else
+			rc = e1_reconfig_bts(bts);
 
-		if (bs11_has_bts1) {
-			bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
-			if (bs11_has_trx1) {
-				struct gsm_bts_trx *trx1;
-				trx1 = gsm_bts_trx_alloc(bts);
-				trx1->arfcn = ARFCN + 2;
-			}
-			bootstrap_bts(bts);
-			rc = e1_config(bts, cardnr+1, release_l2);
-			if (rc < 0)
-				fprintf(stderr, "Error during E1 config of BTS 1\n");
-		}
-		return rc;
-	} else {
-		struct nano_bts_id *bts_id;
-		struct gsm_bts *bts;
-
-		if (llist_empty(&nanobts_ids)) {
-			fprintf(stderr, "You need to specify -i DEVICE_1 -i DEVICE_2 for nanoBTS.\n");
-			return -EINVAL;
-		}
-
-		llist_for_each_entry(bts_id, &nanobts_ids, entry) {
-			bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
-			bootstrap_bts(bts);
-			bts->ip_access.site_id = bts_id->site_id;
-			bts->ip_access.bts_id = 0;
-		}
-
-		return ipaccess_setup(gsmnet);
+		if (rc < 0)
+			exit (1);
 	}
+
+	return 0;
 }
 
 static void create_pcap_file(char *file)
@@ -1178,22 +1103,15 @@
 static void print_help()
 {
 	printf("  Some useful help...\n");
+	printf("  -h --help this text\n");
 	printf("  -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
 	printf("  -s --disable-color\n");
-	printf("  -n --network-code number(MNC) \n");
-	printf("  -c --country-code number (MCC) \n");
-	printf("  -L --location-area-code number (LAC) \n");
-	printf("  -f --arfcn number The frequency ARFCN\n");
 	printf("  -l --database db-name The database to use\n");
 	printf("  -a --authorize-everyone Allow everyone into the network.\n");
 	printf("  -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
 	printf("  -p --pcap file  The filename of the pcap file\n");
-	printf("  -t --bts-type type The BTS type (bs11, nanobts900, nanobts1800)\n");
-	printf("  -i --bts-id=NUMBER The known nanoBTS device numbers. Can be specified multiple times.\n");
 	printf("  -C --cardnr number  For bs11 select E1 card number other than 0\n");
 	printf("  -R --release-l2 Releases mISDN layer 2 after exit, to unload driver.\n");
-	printf("  -2 --second-bs11 Configure + Use a second BS-11\n");
-	printf("  -h --help this text\n");
 }
 
 static void handle_options(int argc, char** argv)
@@ -1204,29 +1122,18 @@
 			{"help", 0, 0, 'h'},
 			{"debug", 1, 0, 'd'},
 			{"disable-color", 0, 0, 's'},
-			{"network-code", 1, 0, 'n'},
-			{"country-code", 1, 0, 'c'},
-			{"location-area-code", 1, 0, 'L'},
 			{"database", 1, 0, 'l'},
 			{"authorize-everyone", 0, 0, 'a'},
 			{"reject-cause", 1, 0, 'r'},
 			{"pcap", 1, 0, 'p'},
-			{"arfcn", 1, 0, 'f'},
-			{"bts-type", 1, 0, 't'},
 			{"cardnr", 1, 0, 'C'},
 			{"release-l2", 0, 0, 'R'},
 			{"timestamp", 0, 0, 'T'},
-			{"band", 0, 0, 'b'},
-			{"bts-id", 1, 0, 'i'},
-			{"tsc", 1, 0, 'S'},
-			{"bsic", 1, 0, 'B'},
 			{"rtp-proxy", 0, 0, 'P'},
-			{"trx1", 0, 0, '1'},
-			{"second-bs11", 0, 0, '2'},
 			{0, 0, 0, 0}
 		};
 
-		c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:i:S:B:P12",
+		c = getopt_long(argc, argv, "hd:sl:ar:p:C:RTP",
 				long_options, &option_index);
 		if (c == -1)
 			break;
@@ -1242,18 +1149,6 @@
 		case 'd':
 			debug_parse_category_mask(optarg);
 			break;
-		case 'n':
-			MNC = atoi(optarg);
-			break;
-		case 'c':
-			MCC = atoi(optarg);
-			break;
-		case 'L':
-			LAC = atoi(optarg);
-			break;
-		case 'f':
-			ARFCN = atoi(optarg);
-			break;
 		case 'l':
 			database_name = strdup(optarg);
 			break;
@@ -1278,35 +1173,9 @@
 		case 'T':
 			debug_timestamp(1);
 			break;
-		case 'b':
-			BAND = gsm_band_parse(atoi(optarg));
-			break;
-		case 'i': {
-			struct nano_bts_id *bts_id = talloc_zero(tall_bsc_ctx, struct nano_bts_id);
-			if (!bts_id) {
-				fprintf(stderr, "Failed to allocate bts id\n");
-				exit(-1);
-			}
-
-			bts_id->site_id = atoi(optarg);
-			llist_add(&bts_id->entry, &nanobts_ids);
-			break;
-		case 'S':
-			TSC = atoi(optarg);
-			break;
-		case 'B':
-			BSIC = atoi(optarg);
-			break;
 		case 'P':
 			ipacc_rtp_direct = 0;
 			break;
-		case '1':
-			bs11_has_trx1 = 1;
-			break;
-		case '2':
-			bs11_has_bts1 = 1;
-			break;
-		}
 		default:
 			/* ignore */
 			break;
diff --git a/openbsc/src/e1_config.c b/openbsc/src/e1_config.c
index 8987803..e743132 100644
--- a/openbsc/src/e1_config.c
+++ b/openbsc/src/e1_config.c
@@ -14,10 +14,106 @@
 #define SAPI_OML	62
 #define SAPI_RSL	0	/* 63 ? */
 
-#define TEI_L2ML	127
-#define TEI_OML		25
-#define TEI_RSL		1
+/* The e1_reconfig_*() functions below tale the configuration present in the
+ * bts/trx/ts data structures and ensure the E1 configuration reflects the
+ * timeslot/subslot/TEI configuration */
 
+int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
+{
+	struct gsm_e1_subslot *e1_link = &ts->e1_link;
+	struct e1inp_line *line;
+	struct e1inp_ts *e1_ts;
+
+	printf("e1_reconfig_ts(%u,%u,%u)\n", ts->trx->bts->nr, ts->trx->nr, ts->nr);
+
+	if (!e1_link->e1_ts)
+		return 0;
+
+	line = e1inp_line_get_create(e1_link->e1_nr);
+	if (!line)
+		return -ENOMEM;
+
+	switch (ts->pchan) {
+	case GSM_PCHAN_TCH_F:
+	case GSM_PCHAN_TCH_H:
+		e1_ts = &line->ts[e1_link->e1_ts-1];
+		e1inp_ts_config(e1_ts, line, E1INP_TS_TYPE_TRAU);
+		subch_demux_activate(&e1_ts->trau.demux, e1_link->e1_ts_ss);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int e1_reconfig_trx(struct gsm_bts_trx *trx)
+{
+	struct gsm_e1_subslot *e1_link = &trx->rsl_e1_link;
+	struct e1inp_ts *sign_ts;
+	struct e1inp_line *line;
+	struct e1inp_sign_link *rsl_link;
+	int i;
+
+	if (!e1_link->e1_ts)
+		return -EINVAL;
+
+	/* RSL Link */
+	line = e1inp_line_get_create(e1_link->e1_nr);
+	if (!line)
+		return -ENOMEM;
+	sign_ts = &line->ts[e1_link->e1_ts-1];
+	e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
+	rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
+					  trx, trx->rsl_tei, SAPI_RSL);
+	if (!rsl_link)
+		return -ENOMEM;
+	if (trx->rsl_link)
+		e1inp_sign_link_destroy(trx->rsl_link);
+	trx->rsl_link = rsl_link;
+
+	for (i = 0; i < TRX_NR_TS; i++)
+		e1_reconfig_ts(&trx->ts[i]);
+
+	return 0;
+}
+
+int e1_reconfig_bts(struct gsm_bts *bts)
+{
+	struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
+	struct e1inp_ts *sign_ts;
+	struct e1inp_line *line;
+	struct e1inp_sign_link *oml_link;
+	struct gsm_bts_trx *trx;
+	int rc;
+
+	printf("e1_reconfig_bts(%u)\n", bts->nr);
+
+	if (!e1_link->e1_ts)
+		return -EINVAL;
+
+	/* OML link */
+	line = e1inp_line_get_create(e1_link->e1_nr);
+	if (!line)
+		return -ENOMEM;
+	sign_ts = &line->ts[e1_link->e1_ts-1];
+	e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
+	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
+					  bts->c0, bts->oml_tei, SAPI_OML);
+	if (!oml_link)
+		return -ENOMEM;
+	if (bts->oml_link)
+		e1inp_sign_link_destroy(bts->oml_link);
+	bts->oml_link = oml_link;
+
+	llist_for_each_entry(trx, &bts->trx_list, list)
+		e1_reconfig_trx(trx);
+
+	/* notify E1 input something has changed */
+	return e1inp_line_update(line);
+}
+
+#if 0
 /* do some compiled-in configuration for our BTS/E1 setup */
 int e1_config(struct gsm_bts *bts, int cardnr, int release_l2)
 {
@@ -102,6 +198,7 @@
 
 	return mi_setup(cardnr, line, release_l2);
 }
+#endif
 
 /* configure pseudo E1 line in ip.access style and connect to BTS */
 int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c
index 7531755..4bc15e5 100644
--- a/openbsc/src/e1_input.c
+++ b/openbsc/src/e1_input.c
@@ -289,6 +289,9 @@
 int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
 		    enum e1inp_ts_type type)
 {
+	if (ts->type == type && ts->line && line)
+		return 0;
+
 	ts->type = type;
 	ts->line = line;
 
@@ -322,6 +325,29 @@
 	return NULL;
 }
 
+struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
+{
+	struct e1inp_line *line;
+	int i;
+
+	line = e1inp_line_get(e1_nr);
+	if (line)
+		return line;
+
+	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
+	if (!line)
+		return NULL;
+
+	line->num = e1_nr;
+	for (i = 0; i < NUM_E1_TS; i++) {
+		line->ts[i].num = i+1;
+		line->ts[i].line = line;
+	}
+	llist_add_tail(&line->list, &e1inp_line_list);
+
+	return line;
+}
+
 static struct e1inp_ts *e1inp_ts_get(u_int8_t e1_nr, u_int8_t ts_nr)
 {
 	struct e1inp_line *e1i_line;
@@ -386,6 +412,12 @@
 	return link;
 }
 
+void e1inp_sign_link_destroy(struct e1inp_sign_link *link)
+{
+	llist_del(&link->list);
+	talloc_free(link);
+}
+
 /* the E1 driver tells us he has received something on a TS */
 int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
 		u_int8_t tei, u_int8_t sapi)
@@ -399,7 +431,7 @@
 		write_pcap_packet(PCAP_INPUT, sapi, tei, msg);
 		link = e1inp_lookup_sign_link(ts, tei, sapi);
 		if (!link) {
-			fprintf(stderr, "didn't find singalling link for "
+			fprintf(stderr, "didn't find signalling link for "
 				"tei %d, sapi %d\n", tei, sapi);
 			return -EINVAL;
 		}
@@ -487,19 +519,9 @@
 	return 0;
 }
 
-/* register a line with the E1 core */
-int e1inp_line_register(struct e1inp_line *line)
+int e1inp_line_update(struct e1inp_line *line)
 {
-	int i;
-
-	for (i = 0; i < NUM_E1_TS; i++) {
-		line->ts[i].num = i+1;
-		line->ts[i].line = line;
-	}
-
-	llist_add_tail(&line->list, &e1inp_line_list);
-	
-	return 0;
+	return mi_e1_line_update(line);
 }
 
 static __attribute__((constructor)) void on_dso_load_e1_inp(void)
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 370c410..edf1b3d 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/talloc.h>
@@ -295,9 +296,15 @@
 	return "invalid";
 }
 
-enum gsm_band gsm_band_parse(int mhz)
+enum gsm_band gsm_band_parse(const char* mhz)
 {
-	switch (mhz) {
+	while (*mhz && !isdigit(*mhz))
+		mhz++;
+
+	if (*mhz == '\0')
+		return -EINVAL;
+
+	switch (atoi(mhz)) {
 	case 400:
 		return GSM_BAND_400;
 	case 850:
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index cee53cc..05786da 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -461,7 +461,7 @@
 	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
 	ret = write(bfd->fd, id_req, sizeof(id_req));
 
-	return e1inp_line_register(line);
+	//return e1inp_line_register(line);
 }
 
 static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
@@ -574,7 +574,7 @@
 	
 	line->driver = &ipaccess_driver;
 
-	return e1inp_line_register(line);
+	//return e1inp_line_register(line);
 }
 
 int ipaccess_setup(struct gsm_network *gsmnet)
diff --git a/openbsc/src/input/misdn.c b/openbsc/src/input/misdn.c
index 2ec74b8..bd655d1 100644
--- a/openbsc/src/input/misdn.c
+++ b/openbsc/src/input/misdn.c
@@ -49,12 +49,6 @@
 #include <openbsc/e1_input.h>
 #include <openbsc/talloc.h>
 
-/* data structure for one E1 interface with A-bis */
-struct mi_e1_handle {
-	/* The mISDN card number of the card we use */
-	int cardnr;
-};
-
 #define TS1_ALLOC_SIZE	300
 
 struct prim_name {
@@ -383,7 +377,6 @@
 
 static int mi_e1_setup(struct e1inp_line *line, int release_l2)
 {
-	struct mi_e1_handle *e1h = line->driver_data;
 	int ts, ret;
 
 	/* TS0 is CRC4, don't need any fd for it */
@@ -422,7 +415,7 @@
 
 		memset(&addr, 0, sizeof(addr));
 		addr.family = AF_ISDN;
-		addr.dev = e1h->cardnr;
+		addr.dev = line->num;
 		switch (e1i_ts->type) {
 		case E1INP_TS_TYPE_SIGN:
 			addr.channel = 0;
@@ -471,20 +464,23 @@
 	return 0;
 }
 
-int mi_setup(int cardnr,  struct e1inp_line *line, int release_l2)
+int mi_e1_line_update(struct e1inp_line *line)
 {
-	struct mi_e1_handle *e1h;
-	int sk, ret, cnt;
 	struct mISDN_devinfo devinfo;
+	int sk, ret, cnt;
 
-	/* create the actual line instance */
-	e1h = talloc(tall_bsc_ctx, struct mi_e1_handle);
-	memset(e1h, 0, sizeof(*e1h));
+	if (!line->driver) {
+		/* this must be the first update */
+		line->driver = &misdn_driver;
+	} else {
+		/* this is a subsequent update */
+		/* FIXME: first close all sockets */
+		fprintf(stderr, "incremental line updates not supported yet\n");
+		return 0;
+	}
 
-	e1h->cardnr = cardnr;
-
-	line->driver = &misdn_driver;
-	line->driver_data = e1h;
+	if (line->driver != &misdn_driver)
+		return -EINVAL;
 
 	/* open the ISDN card device */
 	sk = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
@@ -504,11 +500,11 @@
 	//DEBUGP(DMI,"%d device%s found\n", cnt, (cnt==1)?"":"s");
 	printf("%d device%s found\n", cnt, (cnt==1)?"":"s");
 #if 1
-	devinfo.id = e1h->cardnr;
+	devinfo.id = line->num;
 	ret = ioctl(sk, IMGETDEVINFO, &devinfo);
 	if (ret < 0) {
 		fprintf(stdout, "error getting info for device %d: %s\n",
-			e1h->cardnr, strerror(errno));
+			line->num, strerror(errno));
 		return -ENODEV;
 	}
 	fprintf(stdout, "        id:             %d\n", devinfo.id);
@@ -524,11 +520,11 @@
 		return -EINVAL;
 	}
 
-	ret = mi_e1_setup(line, release_l2);
+	ret = mi_e1_setup(line, 1);
 	if (ret)
 		return ret;
 
-	return e1inp_line_register(line);
+	return 0;
 }
 
 static __attribute__((constructor)) void on_dso_load_sms(void)
diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c
index 16e0dfb..f03dcbb 100644
--- a/openbsc/src/vty/command.c
+++ b/openbsc/src/vty/command.c
@@ -1909,27 +1909,49 @@
 
 /* return parent node */
 /* MUST eventually converge on CONFIG_NODE */
-enum node_type node_parent(enum node_type node)
+enum node_type vty_go_parent(struct vty *vty)
 {
-	enum node_type ret;
+	assert(vty->node > CONFIG_NODE);
 
-	assert(node > CONFIG_NODE);
-
-	switch (node) {
-	case BGP_VPNV4_NODE:
-	case BGP_IPV4_NODE:
-	case BGP_IPV4M_NODE:
-	case BGP_IPV6_NODE:
-		ret = BGP_NODE;
+	switch (vty->node) {
+	case GSMNET_NODE:
+		vty->node = CONFIG_NODE;
+		vty->index = NULL;
 		break;
-	case KEYCHAIN_KEY_NODE:
-		ret = KEYCHAIN_NODE;
+	case BTS_NODE:
+		vty->node = GSMNET_NODE;
+		{
+			/* set vty->index correctly ! */
+			struct gsm_bts *bts = vty->index;
+			vty->index = bts->network;
+		}
+		break;
+	case TRX_NODE:
+		vty->node = BTS_NODE;
+		{
+			/* set vty->index correctly ! */
+			struct gsm_bts_trx *trx = vty->index;
+			vty->index = trx->bts;
+		}
+		break;
+	case TS_NODE:
+		vty->node = TRX_NODE;
+		{
+			/* set vty->index correctly ! */
+			struct gsm_bts_trx_ts *ts = vty->index;
+			vty->index = ts->trx;
+		}
+		break;
+	case SUBSCR_NODE:
+		vty->node = VIEW_NODE;
+		subscr_put(vty->index);
+		vty->index = NULL;
 		break;
 	default:
-		ret = CONFIG_NODE;
+		vty->node = CONFIG_NODE;
 	}
 
-	return ret;
+	return vty->node;
 }
 
 /* Execute command by argument vline vector. */
@@ -2052,9 +2074,11 @@
 		    int vtysh)
 {
 	int ret, saved_ret, tried = 0;
-	enum node_type onode, try_node;
+	enum node_type onode;
+	void *oindex;
 
-	onode = try_node = vty->node;
+	onode = vty->node;
+	oindex = vty->index;
 
 	if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
 		vector shifted_vline;
@@ -2085,8 +2109,7 @@
 	/* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
 	while (ret != CMD_SUCCESS && ret != CMD_WARNING
 	       && vty->node > CONFIG_NODE) {
-		try_node = node_parent(try_node);
-		vty->node = try_node;
+		vty_go_parent(vty);
 		ret = cmd_execute_command_real(vline, vty, cmd);
 		tried = 1;
 		if (ret == CMD_SUCCESS || ret == CMD_WARNING) {
@@ -2096,8 +2119,10 @@
 	}
 	/* no command succeeded, reset the vty to the original node and
 	   return the error for this node */
-	if (tried)
+	if (tried) {
 		vty->node = onode;
+		vty->index = oindex;
+	}
 	return saved_ret;
 }
 
@@ -2232,7 +2257,7 @@
 		while (ret != CMD_SUCCESS && ret != CMD_WARNING
 		       && ret != CMD_ERR_NOTHING_TODO
 		       && vty->node != CONFIG_NODE) {
-			vty->node = node_parent(vty->node);
+			vty_go_parent(vty);
 			ret = cmd_execute_command_strict(vline, vty, NULL);
 		}
 
@@ -2332,29 +2357,9 @@
 		vty->node = ENABLE_NODE;
 		vty_config_unlock(vty);
 		break;
-	case INTERFACE_NODE:
-	case ZEBRA_NODE:
-	case BGP_NODE:
-	case RIP_NODE:
-	case RIPNG_NODE:
-	case OSPF_NODE:
-	case OSPF6_NODE:
-	case ISIS_NODE:
-	case KEYCHAIN_NODE:
-	case MASC_NODE:
-	case RMAP_NODE:
 	case VTY_NODE:
 		vty->node = CONFIG_NODE;
 		break;
-	case BGP_VPNV4_NODE:
-	case BGP_IPV4_NODE:
-	case BGP_IPV4M_NODE:
-	case BGP_IPV6_NODE:
-		vty->node = BGP_NODE;
-		break;
-	case KEYCHAIN_KEY_NODE:
-		vty->node = KEYCHAIN_NODE;
-		break;
 	default:
 		break;
 	}
@@ -2375,22 +2380,6 @@
 		/* Nothing to do. */
 		break;
 	case CONFIG_NODE:
-	case INTERFACE_NODE:
-	case ZEBRA_NODE:
-	case RIP_NODE:
-	case RIPNG_NODE:
-	case BGP_NODE:
-	case BGP_VPNV4_NODE:
-	case BGP_IPV4_NODE:
-	case BGP_IPV4M_NODE:
-	case BGP_IPV6_NODE:
-	case RMAP_NODE:
-	case OSPF_NODE:
-	case OSPF6_NODE:
-	case ISIS_NODE:
-	case KEYCHAIN_NODE:
-	case KEYCHAIN_KEY_NODE:
-	case MASC_NODE:
 	case VTY_NODE:
 		vty_config_unlock(vty);
 		vty->node = ENABLE_NODE;
@@ -3350,8 +3339,7 @@
 
 	/* Default host value settings. */
 	host.name = NULL;
-	//host.password = NULL;
-	host.password = "foo";
+	host.password = NULL;
 	host.enable = NULL;
 	host.logfile = NULL;
 	host.config = NULL;
diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c
index 5472fa0..b403a7b 100644
--- a/openbsc/src/vty/vty.c
+++ b/openbsc/src/vty/vty.c
@@ -743,22 +743,6 @@
 		/* Nothing to do. */
 		break;
 	case CONFIG_NODE:
-	case INTERFACE_NODE:
-	case ZEBRA_NODE:
-	case RIP_NODE:
-	case RIPNG_NODE:
-	case BGP_NODE:
-	case BGP_VPNV4_NODE:
-	case BGP_IPV4_NODE:
-	case BGP_IPV4M_NODE:
-	case BGP_IPV6_NODE:
-	case RMAP_NODE:
-	case OSPF_NODE:
-	case OSPF6_NODE:
-	case ISIS_NODE:
-	case KEYCHAIN_NODE:
-	case KEYCHAIN_KEY_NODE:
-	case MASC_NODE:
 	case VTY_NODE:
 		vty_config_unlock(vty);
 		vty->node = ENABLE_NODE;
@@ -1125,18 +1109,6 @@
 		/* Nothing to do. */
 		break;
 	case CONFIG_NODE:
-	case INTERFACE_NODE:
-	case ZEBRA_NODE:
-	case RIP_NODE:
-	case RIPNG_NODE:
-	case BGP_NODE:
-	case RMAP_NODE:
-	case OSPF_NODE:
-	case OSPF6_NODE:
-	case ISIS_NODE:
-	case KEYCHAIN_NODE:
-	case KEYCHAIN_KEY_NODE:
-	case MASC_NODE:
 	case VTY_NODE:
 		vty_config_unlock(vty);
 		vty->node = ENABLE_NODE;
@@ -1393,7 +1365,7 @@
 			fprintf(stderr, "Ambiguous command.\n");
 			break;
 		case CMD_ERR_NO_MATCH:
-			fprintf(stderr, "Ther is no such command.\n");
+			fprintf(stderr, "There is no such command.\n");
 			break;
 		}
 		fprintf(stderr, "Error occurred during reading below "
@@ -1675,10 +1647,8 @@
 	install_element(ENABLE_NODE, &show_history_cmd);
 
 	install_default(VTY_NODE);
-#if 0
 	install_element(VTY_NODE, &vty_login_cmd);
 	install_element(VTY_NODE, &no_vty_login_cmd);
-#endif
 }
 
 int vty_read_config_file(const char *file_name)
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index 45b2c74..b4aa9f4 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -164,13 +164,41 @@
 	return CMD_SUCCESS;
 }
 
+/* utility functions */
+static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line,
+			  const char *ts, const char *ss)
+{
+	e1_link->e1_nr = atoi(line);
+	e1_link->e1_ts = atoi(ts);
+	if (!strcmp(ss, "full"))
+		e1_link->e1_ts_ss = 255;
+	else
+		e1_link->e1_ts_ss = atoi(ss);
+}
+
+static void config_write_e1_link(struct vty *vty, struct gsm_e1_subslot *e1_link,
+				 const char *prefix)
+{
+	if (!e1_link->e1_ts)
+		return;
+
+	if (e1_link->e1_ts_ss == 255)
+		vty_out(vty, "%se1 line %u timeslot %u sub-slot full%s",
+			prefix, e1_link->e1_nr, e1_link->e1_ts, VTY_NEWLINE);
+	else
+		vty_out(vty, "%se1 line %u timeslot %u sub-slot %u%s",
+			prefix, e1_link->e1_nr, e1_link->e1_ts,
+			e1_link->e1_ts_ss, VTY_NEWLINE);
+}
+
+
 static void config_write_ts_single(struct vty *vty, struct gsm_bts_trx_ts *ts)
 {
-	vty_out(vty, "    ts %u%s", ts->nr, VTY_NEWLINE);
-	vty_out(vty, "     phys_chan_config %s%s", gsm_pchan_name(ts->pchan),
-		VTY_NEWLINE);
-	vty_out(vty, "     e1_subslot %u %u %u%s", ts->e1_link.e1_nr,
-		ts->e1_link.e1_ts, ts->e1_link.e1_ts_ss, VTY_NEWLINE);
+	vty_out(vty, "    timeslot %u%s", ts->nr, VTY_NEWLINE);
+	if (ts->pchan != GSM_PCHAN_NONE)
+		vty_out(vty, "     phys_chan_config %s%s",
+			gsm_pchan_name(ts->pchan), VTY_NEWLINE);
+	config_write_e1_link(vty, &ts->e1_link, "     ");
 }
 
 static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
@@ -180,6 +208,8 @@
 	vty_out(vty, "  trx %u%s", trx->nr, VTY_NEWLINE);
 	vty_out(vty, "   arfcn %u%s", trx->arfcn, VTY_NEWLINE);
 	vty_out(vty, "   max_power_red %u%s", trx->max_power_red, VTY_NEWLINE);
+	config_write_e1_link(vty, &trx->rsl_e1_link, "   rsl ");
+	vty_out(vty, "   rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE);
 
 	for (i = 0; i < TRX_NR_TS; i++)
 		config_write_ts_single(vty, &trx->ts[i]);
@@ -199,6 +229,10 @@
 	if (is_ipaccess_bts(bts))
 		vty_out(vty, "  ip.access unit_id %u %u%s",
 			bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
+	else {
+		config_write_e1_link(vty, &bts->oml_e1_link, "  oml ");
+		vty_out(vty, "  oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE);
+	}
 
 	llist_for_each_entry(trx, &bts->trx_list, list)
 		config_write_trx_single(vty, trx);
@@ -217,10 +251,10 @@
 static int config_write_net(struct vty *vty)
 {
 	vty_out(vty, "network%s", VTY_NEWLINE);
-	vty_out(vty, " country code %u%s", gsmnet->country_code, VTY_NEWLINE);
+	vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
 	vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
-	vty_out(vty, " short name '%s'%s", gsmnet->name_short, VTY_NEWLINE);
-	vty_out(vty, " long name '%s'%s", gsmnet->name_long, VTY_NEWLINE);
+	vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
+	vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
 
 	return CMD_SUCCESS;
 }
@@ -230,9 +264,9 @@
 	vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
 		trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE);
 	vty_out(vty, "  RF Nominal Power: %d dBm, reduced by %u dB, "
-		"resulting BS power: %d dBm\n",
+		"resulting BS power: %d dBm%s",
 		trx->nominal_power, trx->max_power_red,
-		trx->nominal_power - trx->max_power_red);
+		trx->nominal_power - trx->max_power_red, VTY_NEWLINE);
 	vty_out(vty, "  NM State: ");
 	net_dump_nmstate(vty, &trx->nm_state);
 	vty_out(vty, "  Baseband Transceiver NM State: ");
@@ -550,6 +584,8 @@
 
 static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts)
 {
+	if (ts->type == E1INP_TS_TYPE_NONE)
+		return;
 	vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s",
 		ts->num, ts->line->num, e1inp_tstype_name(ts->type),
 		VTY_NEWLINE);
@@ -776,7 +812,7 @@
       "Set the frequency band of this BTS\n")
 {
 	struct gsm_bts *bts = vty->index;
-	int band = gsm_band_parse(atoi(argv[0]));
+	int band = gsm_band_parse(argv[0]);
 
 	if (band < 0) {
 		vty_out(vty, "%% BAND %d is not a valid GSM band%s",
@@ -834,7 +870,7 @@
 	int bsic = atoi(argv[0]);
 
 	if (bsic < 0 || bsic > 0x3f) {
-		vty_out(vty, "%% TSC %d is not in the valid range (0-255)%s",
+		vty_out(vty, "%% BSIC %d is not in the valid range (0-255)%s",
 			bsic, VTY_NEWLINE);
 		return CMD_WARNING;
 	}
@@ -875,6 +911,31 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_bts_oml_e1,
+      cfg_bts_oml_e1_cmd,
+      "oml e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
+      "E1 interface to be used for OML\n")
+{
+	struct gsm_bts *bts = vty->index;
+
+	parse_e1_link(&bts->oml_e1_link, argv[0], argv[1], argv[2]);
+
+	return CMD_SUCCESS;
+}
+
+
+DEFUN(cfg_bts_oml_e1_tei,
+      cfg_bts_oml_e1_tei_cmd,
+      "oml e1 tei <0-63>",
+      "Set the TEI to be used for OML")
+{
+	struct gsm_bts *bts = vty->index;
+
+	bts->oml_tei = atoi(argv[0]);
+
+	return CMD_SUCCESS;
+}
+
 /* per TRX configuration */
 DEFUN(cfg_trx,
       cfg_trx_cmd,
@@ -951,10 +1012,35 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_trx_rsl_e1,
+      cfg_trx_rsl_e1_cmd,
+      "rsl e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
+      "E1 interface to be used for RSL\n")
+{
+	struct gsm_bts_trx *trx = vty->index;
+
+	parse_e1_link(&trx->rsl_e1_link, argv[0], argv[1], argv[2]);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trx_rsl_e1_tei,
+      cfg_trx_rsl_e1_tei_cmd,
+      "rsl e1 tei <0-63>",
+      "Set the TEI to be used for RSL")
+{
+	struct gsm_bts_trx *trx = vty->index;
+
+	trx->rsl_tei = atoi(argv[0]);
+
+	return CMD_SUCCESS;
+}
+
+
 /* per TS configuration */
 DEFUN(cfg_ts,
       cfg_ts_cmd,
-      "timeslot TS_NR",
+      "timeslot <0-7>",
       "Select a Timeslot to configure")
 {
 	int ts_nr = atoi(argv[0]);
@@ -994,14 +1080,12 @@
 
 DEFUN(cfg_ts_e1_subslot,
       cfg_ts_e1_subslot_cmd,
-      "e1_subslot E1_IF <1-31> <0-4>",
+      "e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
       "E1 sub-slot connected to this on-air timeslot")
 {
 	struct gsm_bts_trx_ts *ts = vty->index;
 
-	ts->e1_link.e1_nr = atoi(argv[0]);
-	ts->e1_link.e1_ts = atoi(argv[1]);
-	ts->e1_link.e1_ts_ss = atoi(argv[2]);
+	parse_e1_link(&ts->e1_link, argv[0], argv[1], argv[2]);
 
 	return CMD_SUCCESS;
 }
@@ -1158,6 +1242,7 @@
 	install_element(CONFIG_NODE, &cfg_net_cmd);
 	install_node(&net_node, config_write_net);
 	install_default(GSMNET_NODE);
+	install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
 	install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
 	install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
 	install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
@@ -1169,13 +1254,18 @@
 	install_element(BTS_NODE, &cfg_bts_band_cmd);
 	install_element(BTS_NODE, &cfg_bts_lac_cmd);
 	install_element(BTS_NODE, &cfg_bts_tsc_cmd);
+	install_element(BTS_NODE, &cfg_bts_bsic_cmd);
 	install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
+	install_element(BTS_NODE, &cfg_bts_oml_e1_cmd);
+	install_element(BTS_NODE, &cfg_bts_oml_e1_tei_cmd);
 
 	install_element(BTS_NODE, &cfg_trx_cmd);
 	install_node(&trx_node, dummy_config_write);
 	install_default(TRX_NODE);
 	install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
 	install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
+	install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
+	install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd);
 
 	install_element(TRX_NODE, &cfg_ts_cmd);
 	install_node(&ts_node, dummy_config_write);