Merge branch 'holger/bsc-msc-separation'
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 483997a..6a87782 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -7,5 +7,5 @@
 		 silent_call.h mgcp.h meas_rep.h rest_octets.h \
 		 system_information.h handover.h mgcp_internal.h
 
-openbsc_HEADERS = gsm_04_08.h meas_rep.h
+openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
 openbscdir = $(includedir)/openbsc
diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h
new file mode 100644
index 0000000..51e344f
--- /dev/null
+++ b/openbsc/include/openbsc/bsc_api.h
@@ -0,0 +1,6 @@
+/* GSM 08.08 like API for OpenBSC */
+
+#include "gsm_data.h"
+
+
+int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id);
diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h
index 9badd36..8127af1 100644
--- a/openbsc/include/openbsc/gsm_04_11.h
+++ b/openbsc/include/openbsc/gsm_04_11.h
@@ -25,7 +25,7 @@
 
 int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id);
 
-int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms);
+int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms);
 
 struct gsm_sms *sms_alloc(void);
 void sms_free(struct gsm_sms *sms);
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 88e7f16..f352711 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -84,18 +84,18 @@
  * will be started.
  */
 #define LCHAN_RELEASE_TIMEOUT 20, 0
-#define use_lchan(lchan) \
-	do {	lchan->use_count++; \
+#define use_subscr_con(con) \
+	do {	(con)->use_count++; \
 		DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \
-			lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
-			lchan->nr, lchan->use_count); \
-		bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
+			(con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \
+			(con)->lchan->nr, (con)->use_count); \
+		bsc_schedule_timer(&(con)->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
 
-#define put_lchan(lchan) \
-	do { lchan->use_count--; \
+#define put_subscr_con(con) \
+	do { (con)->use_count--; \
 		DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \
-			lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
-			lchan->nr, lchan->use_count); \
+			(con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \
+			(con)->lchan->nr, (con)->use_count); \
 	} while(0);
 
 
@@ -182,6 +182,30 @@
 	LCHAN_S_INACTIVE,	/* channel is set inactive */
 };
 
+/* the per subscriber data for lchan */
+struct gsm_subscriber_connection {
+	/* To whom we are allocated at the moment */
+	struct gsm_subscriber *subscr;
+
+	/* Timer started to release the channel */
+	struct timer_list release_timer;
+
+	/*
+	 * Operations that have a state and might be pending
+	 */
+	struct gsm_loc_updating_operation *loc_operation;
+
+	/* use count. how many users use this channel */
+	unsigned int use_count;
+
+	/* Are we part of a special "silent" call */
+	int silent_call;
+
+	/* back pointers */
+	struct gsm_lchan *lchan;
+	struct gsm_bts *bts;
+};
+
 struct gsm_lchan {
 	/* The TS that we're part of */
 	struct gsm_bts_trx_ts *ts;
@@ -204,31 +228,15 @@
 		u_int8_t key_len;
 		u_int8_t key[MAX_A5_KEY_LEN];
 	} encr;
-	/* Are we part of a special "silent" call */
-	int silent_call;
+
+	struct timer_list T3101;
 
 	/* AMR bits */
 	struct gsm48_multi_rate_conf mr_conf;
 	
-	/* To whom we are allocated at the moment */
-	struct gsm_subscriber *subscr;
-
-	/* Timer started to release the channel */
-	struct timer_list release_timer;
-
-	struct timer_list T3101;
-
 	/* Established data link layer services */
 	u_int8_t sapis[8];
 
-	/*
-	 * Operations that have a state and might be pending
-	 */
-	struct gsm_loc_updating_operation *loc_operation;
-
-	/* use count. how many users use this channel */
-	unsigned int use_count;
-
 	/* cache of last measurement reports on this lchan */
 	struct gsm_meas_rep meas_rep[6];
 	int meas_rep_idx;
@@ -246,6 +254,8 @@
 		u_int8_t speech_mode;
 		struct rtp_socket *rtp_socket;
 	} abis_ip;
+
+	struct gsm_subscriber_connection conn;
 };
 
 struct gsm_e1_subslot {
diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h
index 50c3cc5..90a008b 100644
--- a/openbsc/include/openbsc/transaction.h
+++ b/openbsc/include/openbsc/transaction.h
@@ -20,8 +20,8 @@
 	/* To whom we belong, unique identifier of remote MM entity */
 	struct gsm_subscriber *subscr;
 
-	/* The LCHAN that we're currently using to transmit messages */
-	struct gsm_lchan *lchan;
+	/* The associated connection we are using to transmit messages */
+	struct gsm_subscriber_connection *conn;
 
 	/* reference from MNCC or other application */
 	u_int32_t callref;
@@ -71,6 +71,6 @@
 
 /* update all transactions to use a different LCHAN, e.g.
  * after handover has succeeded */
-int trans_lchan_change(struct gsm_lchan *lchan_old,
-		       struct gsm_lchan *lchan_new);
+int trans_lchan_change(struct gsm_subscriber_connection *conn_old,
+		       struct gsm_subscriber_connection *conn_new);
 #endif
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 1d18475..cbc809d 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -17,7 +17,7 @@
 		input/misdn.c input/ipaccess.c \
 		talloc_ctx.c system_information.c rest_octets.c \
 		rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \
-		bts_unknown.c bsc_version.c
+		bts_unknown.c bsc_version.c bsc_api.c
 
 libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \
 		mncc.c gsm_04_08.c gsm_04_11.c transaction.c \
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index e7844af..0c3b597 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -119,7 +119,7 @@
 
 	lchan = &ts->lchan[lch_idx];
 	debug_set_context(BSC_CTX_LCHAN, lchan);
-	debug_set_context(BSC_CTX_SUBSCR, lchan->subscr);
+	debug_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr);
 
 	return lchan;
 }
diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c
new file mode 100644
index 0000000..b504752
--- /dev/null
+++ b/openbsc/src/bsc_api.c
@@ -0,0 +1,33 @@
+/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/bsc_api.h>
+#include <openbsc/abis_rsl.h>
+
+
+int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
+			struct msgb *msg, int link_id)
+{
+	msg->lchan = conn->lchan;
+	msg->trx = msg->lchan->ts->trx;
+	return rsl_data_request(msg, link_id);
+}
diff --git a/openbsc/src/bsc_rll.c b/openbsc/src/bsc_rll.c
index 1551d94..9a4f5aa 100644
--- a/openbsc/src/bsc_rll.c
+++ b/openbsc/src/bsc_rll.c
@@ -51,8 +51,11 @@
 
 static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type)
 {
+	struct gsm_subscriber_connection *conn;
+
+	conn = &rllr->lchan->conn;
 	llist_del(&rllr->list);
-	put_lchan(rllr->lchan);
+	put_subscr_con(conn);
 	rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
 	talloc_free(rllr);
 }
@@ -70,6 +73,7 @@
 			     enum bsc_rllr_ind),
 		  void *data)
 {
+	struct gsm_subscriber_connection *conn;
 	struct bsc_rll_req *rllr = talloc_zero(tall_bsc_ctx, struct bsc_rll_req);
 	u_int8_t link_id;
 	if (!rllr)
@@ -83,7 +87,8 @@
 	     lchan->type == GSM_LCHAN_TCH_H) && sapi != 0)
 		link_id |= 0x40;
 
-	use_lchan(lchan);
+	conn = &lchan->conn;
+	use_subscr_con(conn);
 	rllr->lchan = lchan;
 	rllr->link_id = link_id;
 	rllr->cb = cb;
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 2e88524..c8e358d 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -252,7 +252,6 @@
 
 	if (lchan) {
 		lchan->type = type;
-		lchan->use_count = 0;
 
 		/* clear sapis */
 		memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis));
@@ -260,10 +259,16 @@
 		/* clear multi rate config */
 		memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf));
 
+		/* clear per MSC/BSC data */
+		memset(&lchan->conn, 0, sizeof(lchan->conn));
+
 		/* Configure the time and start it so it will be closed */
-		lchan->release_timer.cb = auto_release_channel;
-		lchan->release_timer.data = lchan;
-		bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
+		lchan->conn.lchan = lchan;
+		lchan->conn.bts = lchan->ts->trx->bts;
+		lchan->conn.release_timer.cb = auto_release_channel;
+		lchan->conn.release_timer.data = lchan;
+		bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
+
 	}
 
 	return lchan;
@@ -275,19 +280,19 @@
 	int i;
 
 	lchan->type = GSM_LCHAN_NONE;
-	if (lchan->subscr) {
-		subscr_put(lchan->subscr);
-		lchan->subscr = NULL;
+	if (lchan->conn.subscr) {
+		subscr_put(lchan->conn.subscr);
+		lchan->conn.subscr = NULL;
 	}
 
 	/* We might kill an active channel... */
-	if (lchan->use_count != 0) {
+	if (lchan->conn.use_count != 0) {
 		dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan);
-		lchan->use_count = 0;
+		lchan->conn.use_count = 0;
 	}
 
 	/* stop the timer */
-	bsc_del_timer(&lchan->release_timer);
+	bsc_del_timer(&lchan->conn.release_timer);
 	bsc_del_timer(&lchan->T3101);
 
 	/* clear cached measuement reports */
@@ -299,7 +304,7 @@
 	for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
 		lchan->neigh_meas[i].arfcn = 0;
 
-	lchan->silent_call = 0;
+	lchan->conn.silent_call = 0;
 
 	/* FIXME: ts_free() the timeslot, if we're the last logical
 	 * channel using it */
@@ -308,19 +313,19 @@
 /* Consider releasing the channel now */
 int lchan_auto_release(struct gsm_lchan *lchan)
 {
-	if (lchan->use_count > 0) {
+	if (lchan->conn.use_count > 0) {
 		return 0;
 	}
 
 	/* Assume we have GSM04.08 running and send a release */
-	if (lchan->subscr) {
+	if (lchan->conn.subscr) {
 		gsm48_send_rr_release(lchan);
 	}
 
 	/* spoofed? message */
-	if (lchan->use_count < 0)
+	if (lchan->conn.use_count < 0)
 		LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n",
-			lchan->use_count);
+			lchan->conn.use_count);
 
 	DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
 	rsl_release_request(lchan, 0);
@@ -333,7 +338,7 @@
 	struct gsm_lchan *lchan = _lchan;
 
 	if (!lchan_auto_release(lchan))
-		bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
+		bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
 }
 
 struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) {
@@ -345,7 +350,7 @@
 			for (lchan_no = 0; lchan_no < TS_MAX_LCHAN; ++lchan_no) {
 				struct gsm_lchan *lchan =
 					&trx->ts[ts_no].lchan[lchan_no];
-				if (subscr == lchan->subscr)
+				if (subscr == lchan->conn.subscr)
 					return lchan;
 			}
 		}
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 2eda0bd..2376c63 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -58,7 +58,7 @@
 int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
 static int gsm48_tx_simple(struct gsm_lchan *lchan,
 			   u_int8_t pdisc, u_int8_t msg_type);
-static void schedule_reject(struct gsm_lchan *lchan);
+static void schedule_reject(struct gsm_subscriber_connection *conn);
 
 struct gsm_lai {
 	u_int16_t mcc;
@@ -96,35 +96,35 @@
 	}
 }
 
-static void release_loc_updating_req(struct gsm_lchan *lchan)
+static void release_loc_updating_req(struct gsm_subscriber_connection *conn)
 {
-	if (!lchan->loc_operation)
+	if (!conn->loc_operation)
 		return;
 
-	bsc_del_timer(&lchan->loc_operation->updating_timer);
-	talloc_free(lchan->loc_operation);
-	lchan->loc_operation = 0;
-	put_lchan(lchan);
+	bsc_del_timer(&conn->loc_operation->updating_timer);
+	talloc_free(conn->loc_operation);
+	conn->loc_operation = 0;
+	put_subscr_con(conn);
 }
 
-static void allocate_loc_updating_req(struct gsm_lchan *lchan)
+static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn)
 {
-	use_lchan(lchan);
-	release_loc_updating_req(lchan);
+	use_subscr_con(conn)
+	release_loc_updating_req(conn);
 
-	lchan->loc_operation = talloc_zero(tall_locop_ctx,
+	conn->loc_operation = talloc_zero(tall_locop_ctx,
 					   struct gsm_loc_updating_operation);
 }
 
-static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
+static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
-	if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
+	if (authorize_subscriber(conn->loc_operation, conn->subscr)) {
 		int rc;
 
-		db_subscriber_alloc_tmsi(lchan->subscr);
-		release_loc_updating_req(lchan);
-		rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi);
-		if (lchan->ts->trx->bts->network->send_mm_info) {
+		db_subscriber_alloc_tmsi(conn->subscr);
+		release_loc_updating_req(conn);
+		rc = gsm0408_loc_upd_acc(msg->lchan, conn->subscr->tmsi);
+		if (msg->lchan->ts->trx->bts->network->send_mm_info) {
 			/* send MM INFO with network name */
 			rc = gsm48_tx_mm_info(msg->lchan);
 		}
@@ -132,10 +132,11 @@
 		/* call subscr_update after putting the loc_upd_acc
 		 * in the transmit queue, since S_SUBSCR_ATTACHED might
 		 * trigger further action like SMS delivery */
-		subscr_update(lchan->subscr, msg->trx->bts,
+		subscr_update(conn->subscr, msg->trx->bts,
 			      GSM_SUBSCRIBER_UPDATE_ATTACHED);
+
 		/* try to close channel ASAP */
-		lchan_auto_release(lchan);
+		lchan_auto_release(conn->lchan);
 		return rc;
 	}
 
@@ -158,14 +159,14 @@
 	if (!lchan)
 		return 0;
 
-	release_loc_updating_req(lchan);
+	release_loc_updating_req(&lchan->conn);
 
 	/* Free all transactions that are associated with the released lchan */
 	/* FIXME: this is not neccessarily the right thing to do, we should
 	 * only set trans->lchan to NULL and wait for another lchan to be
 	 * established to the same MM entity (phone/subscriber) */
 	llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
-		if (trans->lchan == lchan)
+		if (trans->conn && trans->conn->lchan == lchan)
 			trans_free(trans);
 	}
 
@@ -175,11 +176,13 @@
 /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
 int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
 {
+	struct gsm_subscriber_connection *conn;
 	struct gsm_bts *bts = lchan->ts->trx->bts;
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	
 	msg->lchan = lchan;
+	conn = &lchan->conn;
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
 	gh->proto_discr = GSM48_PDISC_MM;
@@ -187,8 +190,8 @@
 	gh->data[0] = cause;
 
 	LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT "
-	     "LAC=%u BTS=%u\n", lchan->subscr ?
-	     			subscr_name(lchan->subscr) : "unknown",
+	     "LAC=%u BTS=%u\n", conn->subscr ?
+	     			subscr_name(conn->subscr) : "unknown",
 	     lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr);
 
 	counter_inc(bts->network->stats.loc_upd_resp.reject);
@@ -245,6 +248,7 @@
 /* Parse Chapter 9.2.11 Identity Response */
 static int mm_rx_id_resp(struct msgb *msg)
 {
+	struct gsm_subscriber_connection *conn;
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	struct gsm_lchan *lchan = msg->lchan;
 	struct gsm_bts *bts = lchan->ts->trx->bts;
@@ -256,51 +260,54 @@
 	DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
 		mi_type, mi_string);
 
+	conn = &lchan->conn;
+
 	dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data);
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
 		/* look up subscriber based on IMSI, create if not found */
-		if (!lchan->subscr) {
-			lchan->subscr = subscr_get_by_imsi(net, mi_string);
-			if (!lchan->subscr)
-				lchan->subscr = db_create_subscriber(net, mi_string);
+		if (!conn->subscr) {
+			conn->subscr = subscr_get_by_imsi(net, mi_string);
+			if (!conn->subscr)
+				conn->subscr = db_create_subscriber(net, mi_string);
 		}
-		if (lchan->loc_operation)
-			lchan->loc_operation->waiting_for_imsi = 0;
+		if (conn->loc_operation)
+			conn->loc_operation->waiting_for_imsi = 0;
 		break;
 	case GSM_MI_TYPE_IMEI:
 	case GSM_MI_TYPE_IMEISV:
 		/* update subscribe <-> IMEI mapping */
-		if (lchan->subscr) {
-			db_subscriber_assoc_imei(lchan->subscr, mi_string);
-			db_sync_equipment(&lchan->subscr->equipment);
+		if (conn->subscr) {
+			db_subscriber_assoc_imei(conn->subscr, mi_string);
+			db_sync_equipment(&conn->subscr->equipment);
 		}
-		if (lchan->loc_operation)
-			lchan->loc_operation->waiting_for_imei = 0;
+		if (conn->loc_operation)
+			conn->loc_operation->waiting_for_imei = 0;
 		break;
 	}
 
 	/* Check if we can let the mobile station enter */
-	return gsm0408_authorize(lchan, msg);
+	return gsm0408_authorize(conn, msg);
 }
 
 
 static void loc_upd_rej_cb(void *data)
 {
-	struct gsm_lchan *lchan = data;
+	struct gsm_subscriber_connection *conn = data;
+	struct gsm_lchan *lchan = conn->lchan;
 	struct gsm_bts *bts = lchan->ts->trx->bts;
 
-	release_loc_updating_req(lchan);
+	release_loc_updating_req(conn);
 	gsm0408_loc_upd_rej(lchan, bts->network->reject_cause);
 	lchan_auto_release(lchan);
 }
 
-static void schedule_reject(struct gsm_lchan *lchan)
+static void schedule_reject(struct gsm_subscriber_connection *conn)
 {
-	lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
-	lchan->loc_operation->updating_timer.data = lchan;
-	bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
+	conn->loc_operation->updating_timer.cb = loc_upd_rej_cb;
+	conn->loc_operation->updating_timer.data = conn;
+	bsc_schedule_timer(&conn->loc_operation->updating_timer, 5, 0);
 }
 
 static const char *lupd_name(u_int8_t type)
@@ -320,6 +327,7 @@
 /* Chapter 9.2.15: Receive Location Updating Request */
 static int mm_rx_loc_upd_req(struct msgb *msg)
 {
+	struct gsm_subscriber_connection *conn;
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	struct gsm48_loc_upd_req *lu;
 	struct gsm_subscriber *subscr = NULL;
@@ -330,6 +338,7 @@
 	int rc;
 
  	lu = (struct gsm48_loc_upd_req *) gh->data;
+	conn = &lchan->conn;
 
 	mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
 
@@ -356,21 +365,21 @@
 	 * Pseudo Spoof detection: Just drop a second/concurrent
 	 * location updating request.
 	 */
-	if (lchan->loc_operation) {
+	if (conn->loc_operation) {
 		DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
-			lchan->loc_operation);
+			conn->loc_operation);
 		gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
 		return 0;
 	}
 
-	allocate_loc_updating_req(lchan);
+	allocate_loc_updating_req(&lchan->conn);
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
 		DEBUGPC(DMM, "\n");
 		/* we always want the IMEI, too */
 		rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
-		lchan->loc_operation->waiting_for_imei = 1;
+		conn->loc_operation->waiting_for_imei = 1;
 
 		/* look up subscriber based on IMSI, create if not found */
 		subscr = subscr_get_by_imsi(bts->network, mi_string);
@@ -382,7 +391,7 @@
 		DEBUGPC(DMM, "\n");
 		/* we always want the IMEI, too */
 		rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
-		lchan->loc_operation->waiting_for_imei = 1;
+		conn->loc_operation->waiting_for_imei = 1;
 
 		/* look up the subscriber based on TMSI, request IMSI if it fails */
 		subscr = subscr_get_by_tmsi(bts->network,
@@ -390,7 +399,7 @@
 		if (!subscr) {
 			/* send IDENTITY REQUEST message to get IMSI */
 			rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
-			lchan->loc_operation->waiting_for_imsi = 1;
+			conn->loc_operation->waiting_for_imsi = 1;
 		}
 		break;
 	case GSM_MI_TYPE_IMEI:
@@ -404,7 +413,7 @@
 	}
 
 	/* schedule the reject timer */
-	schedule_reject(lchan);
+	schedule_reject(conn);
 
 	if (!subscr) {
 		DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
@@ -412,12 +421,12 @@
 		return -EINVAL;
 	}
 
-	lchan->subscr = subscr;
-	lchan->subscr->equipment.classmark1 = lu->classmark1;
+	conn->subscr = subscr;
+	conn->subscr->equipment.classmark1 = lu->classmark1;
 
 	/* check if we can let the subscriber into our network immediately
 	 * or if we need to wait for identity responses. */
-	return gsm0408_authorize(lchan, msg);
+	return gsm0408_authorize(conn, msg);
 }
 
 #if 0
@@ -566,7 +575,7 @@
 }
 
 /* 9.2.6 CM service reject */
-static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
+static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
 				enum gsm48_reject_value value)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
@@ -574,8 +583,8 @@
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
 
-	msg->lchan = lchan;
-	use_lchan(lchan);
+	msg->lchan = conn->lchan;
+	use_subscr_con(conn);
 
 	gh->proto_discr = GSM48_PDISC_MM;
 	gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
@@ -613,20 +622,20 @@
 	DEBUGP(DMM, "<- CM SERVICE REQUEST ");
 	if (msg->data_len < sizeof(struct gsm48_service_request*)) {
 		DEBUGPC(DMM, "wrong sized message\n");
-		return gsm48_tx_mm_serv_rej(msg->lchan,
+		return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
 					    GSM48_REJECT_INCORRECT_MESSAGE);
 	}
 
 	if (msg->data_len < req->mi_len + 6) {
 		DEBUGPC(DMM, "does not fit in packet\n");
-		return gsm48_tx_mm_serv_rej(msg->lchan,
+		return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
 					    GSM48_REJECT_INCORRECT_MESSAGE);
 	}
 
 	mi_type = mi[0] & GSM_MI_TYPE_MASK;
 	if (mi_type != GSM_MI_TYPE_TMSI) {
 		DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
-		return gsm48_tx_mm_serv_rej(msg->lchan,
+		return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
 					    GSM48_REJECT_INCORRECT_MESSAGE);
 	}
 
@@ -644,12 +653,12 @@
 
 	/* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
 	if (!subscr)
-		return gsm48_tx_mm_serv_rej(msg->lchan,
+		return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
 					    GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
 
-	if (!msg->lchan->subscr)
-		msg->lchan->subscr = subscr;
-	else if (msg->lchan->subscr == subscr)
+	if (!msg->lchan->conn.subscr)
+		msg->lchan->conn.subscr = subscr;
+	else if (msg->lchan->conn.subscr == subscr)
 		subscr_put(subscr); /* lchan already has a ref, don't need another one */
 	else {
 		DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
@@ -749,8 +758,8 @@
 		break;
 	case GSM48_MT_MM_TMSI_REALL_COMPL:
 		DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
-		       msg->lchan->subscr ?
-				subscr_name(msg->lchan->subscr) :
+		       msg->lchan->conn.subscr ?
+				subscr_name(msg->lchan->conn.subscr) :
 				"unknown subscriber");
 		break;
 	case GSM48_MT_MM_IMSI_DETACH_IND:
@@ -815,7 +824,7 @@
 static int gsm48_rx_rr_classmark(struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm_subscriber *subscr = msg->lchan->subscr;
+	struct gsm_subscriber *subscr = msg->lchan->conn.subscr;
 	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
 	u_int8_t cm2_len, cm3_len = 0;
 	u_int8_t *cm2, *cm3 = NULL;
@@ -896,7 +905,7 @@
 	DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
 		apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len));
 
-	return db_apdu_blob_store(msg->lchan->subscr, apdu_id_flags, apdu_len, apdu_data);
+	return db_apdu_blob_store(msg->lchan->conn.subscr, apdu_id_flags, apdu_len, apdu_data);
 }
 
 /* Chapter 9.1.16 Handover complete */
@@ -1062,12 +1071,12 @@
 	struct msgb *msg;
 
 	if (trans)
-		if (trans->lchan)
+		if (trans->conn)
 			DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
 				"Sending '%s' to MNCC.\n",
-				trans->lchan->ts->trx->bts->nr,
-				trans->lchan->ts->trx->nr,
-				trans->lchan->ts->nr, trans->transaction_id,
+				trans->conn->lchan->ts->trx->bts->nr,
+				trans->conn->lchan->ts->trx->nr,
+				trans->conn->lchan->ts->nr, trans->transaction_id,
 				(trans->subscr)?(trans->subscr->extension):"-",
 				get_mncc_name(msg_type));
 		else
@@ -1116,8 +1125,8 @@
 	}
 	if (trans->cc.state != GSM_CSTATE_NULL)
 		new_cc_state(trans, GSM_CSTATE_NULL);
-	if (trans->lchan)
-		trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
+	if (trans->conn)
+		trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref);
 }
 
 static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
@@ -1144,7 +1153,7 @@
 
 	/* check all tranactions (without lchan) for subscriber */
 	llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
-		if (transt->subscr != subscr || transt->lchan)
+		if (transt->subscr != subscr || transt->conn)
 			continue;
 		switch (event) {
 		case GSM_PAGING_SUCCEEDED:
@@ -1153,9 +1162,9 @@
 			DEBUGP(DCC, "Paging subscr %s succeeded!\n",
 				subscr->extension);
 			/* Assign lchan */
-			if (!transt->lchan) {
-				transt->lchan = lchan;
-				use_lchan(lchan);
+			if (!transt->conn) {
+				transt->conn = &lchan->conn;
+				use_subscr_con(transt->conn);
 			}
 			/* send SETUP request to called party */
 			gsm48_cc_tx_setup(transt, &transt->cc.msg);
@@ -1200,7 +1209,7 @@
 		 * a tch_recv_mncc request pending */
 		net = lchan->ts->trx->bts->network;
 		llist_for_each_entry(trans, &net->trans_list, entry) {
-			if (trans->lchan == lchan && trans->tch_recv) {
+			if (trans->conn && trans->conn->lchan == lchan && trans->tch_recv) {
 				DEBUGP(DCC, "pending tch_recv_mncc request\n");
 				tch_recv_mncc(net, trans->callref, 1);
 			}
@@ -1273,11 +1282,11 @@
 	if (!trans1 || !trans2)
 		return -EIO;
 
-	if (!trans1->lchan || !trans2->lchan)
+	if (!trans1->conn || !trans2->conn)
 		return -EIO;
 
 	/* through-connect channel */
-	return tch_map(trans1->lchan, trans2->lchan);
+	return tch_map(trans1->conn->lchan, trans2->conn->lchan);
 }
 
 /* enable receive of channels to MNCC upqueue */
@@ -1292,9 +1301,9 @@
 	trans = trans_find_by_callref(net, callref);
 	if (!trans)
 		return -EIO;
-	if (!trans->lchan)
+	if (!trans->conn)
 		return 0;
-	lchan = trans->lchan;
+	lchan = trans->conn->lchan;
 	bts = lchan->ts->trx->bts;
 
 	switch (bts->type) {
@@ -2490,7 +2499,7 @@
 {
 	struct gsm_mncc *mode = arg;
 
-	return gsm48_lchan_modify(trans->lchan, mode->lchan_mode);
+	return gsm48_lchan_modify(trans->conn->lchan, mode->lchan_mode);
 }
 
 static struct downstate {
@@ -2576,18 +2585,18 @@
 		trans = trans_find_by_callref(net, data->callref);
 		if (!trans)
 			return -EIO;
-		if (!trans->lchan)
+		if (!trans->conn)
 			return 0;
-		if (trans->lchan->type != GSM_LCHAN_TCH_F)
+		if (trans->conn->lchan->type != GSM_LCHAN_TCH_F)
 			return 0;
-		bts = trans->lchan->ts->trx->bts;
+		bts = trans->conn->lchan->ts->trx->bts;
 		switch (bts->type) {
 		case GSM_BTS_TYPE_NANOBTS:
-			if (!trans->lchan->abis_ip.rtp_socket)
+			if (!trans->conn->lchan->abis_ip.rtp_socket)
 				return 0;
-			return rtp_send_frame(trans->lchan->abis_ip.rtp_socket, arg);
+			return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg);
 		case GSM_BTS_TYPE_BS11:
-			return trau_send_frame(trans->lchan, arg);
+			return trau_send_frame(trans->conn->lchan, arg);
 		default:
 			DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
 		}
@@ -2665,6 +2674,7 @@
 		}
 		/* Find lchan */
 		lchan = lchan_for_subscr(subscr);
+
 		/* If subscriber has no lchan */
 		if (!lchan) {
 			/* find transaction with this subscriber already paging */
@@ -2692,11 +2702,13 @@
 			return 0;
 		}
 		/* Assign lchan */
-		trans->lchan = lchan;
-		use_lchan(lchan);
+		trans->conn = &lchan->conn;
+		use_subscr_con(trans->conn);
 		subscr_put(subscr);
 	}
-	lchan = trans->lchan;
+
+	if (trans->conn)
+		lchan = trans->conn->lchan;
 
 	/* if paging did not respond yet */
 	if (!lchan) {
@@ -2719,7 +2731,7 @@
 		"Received '%s' from MNCC in state %d (%s)\n",
 		lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
 		trans->transaction_id,
-		(lchan->subscr)?(lchan->subscr->extension):"-",
+		(trans->conn->subscr)?(trans->conn->subscr->extension):"-",
 		get_mncc_name(msg_type), trans->cc.state,
 		gsm48_cc_state_name(trans->cc.state));
 
@@ -2795,6 +2807,7 @@
 
 static int gsm0408_rcv_cc(struct msgb *msg)
 {
+	struct gsm_subscriber_connection *conn;
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	u_int8_t msg_type = gh->msg_type & 0xbf;
 	u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
@@ -2806,14 +2819,16 @@
 		DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
 		return -EINVAL;
 	}
-	
+
+	conn = &lchan->conn;
+
 	/* Find transaction */
-	trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
+	trans = trans_find_by_id(conn->subscr, GSM48_PDISC_CC, transaction_id);
 
 	DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
 		"Received '%s' from MS in state %d (%s)\n",
 		lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
-		transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
+		transaction_id, (conn->subscr)?(conn->subscr->extension):"-",
 		gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0,
 		gsm48_cc_state_name(trans?(trans->cc.state):0));
 
@@ -2822,7 +2837,7 @@
 		DEBUGP(DCC, "Unknown transaction ID %x, "
 			"creating new trans.\n", transaction_id);
 		/* Create transaction */
-		trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
+		trans = trans_alloc(conn->subscr, GSM48_PDISC_CC,
 				    transaction_id, new_callref++);
 		if (!trans) {
 			DEBUGP(DCC, "No memory for trans.\n");
@@ -2832,8 +2847,8 @@
 			return -ENOMEM;
 		}
 		/* Assign transaction */
-		trans->lchan = lchan;
-		use_lchan(lchan);
+		trans->conn = &lchan->conn;
+		use_subscr_con(trans->conn);
 	}
 
 	/* find function for current state and message */
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index 2472f12..ed3f905 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -57,7 +57,7 @@
 	 * work that the caller no longer has to do */
 	if (trans) {
 		gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
-		msg->lchan = trans->lchan;
+		msg->lchan = trans->conn->lchan;
 	}
 
 	if (msg->lchan) {
@@ -316,16 +316,16 @@
 	if (is_siemens_bts(bts))
 		send_siemens_mrpci(msg->lchan, classmark2_lv);
 
-	if (!msg->lchan->subscr) {
-		msg->lchan->subscr = subscr;
-	} else if (msg->lchan->subscr != subscr) {
+	if (!msg->lchan->conn.subscr) {
+		msg->lchan->conn.subscr = subscr;
+	} else if (msg->lchan->conn.subscr != subscr) {
 		LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n");
 		subscr_put(subscr);
 		return -EINVAL;
 	} else {
 		DEBUGP(DRR, "<- Channel already owned by us\n");
 		subscr_put(subscr);
-		subscr = msg->lchan->subscr;
+		subscr = msg->lchan->conn.subscr;
 	}
 
 	sig_data.subscr = subscr;
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 881c375..e3f37f6 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -24,6 +24,7 @@
  */
 
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -121,16 +122,11 @@
 				   "GSM 04.11");
 }
 
-static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
+static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id)
 {
-	if (msg->lchan)
-		msg->trx = msg->lchan->ts->trx;
-
-	msg->l3h = msg->data;
-
 	DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
-
-	return rsl_data_request(msg, link_id);
+	msg->l3h = msg->data;
+	return gsm0808_submit_dtap(conn, msg, link_id);
 }
 
 /* SMC TC1* is expired */
@@ -154,9 +150,6 @@
 	gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
 	gh->msg_type = msg_type;
 
-	/* assign the outgoing lchan */
-	msg->lchan = trans->lchan;
-
 	/* mobile originating */
 	switch (gh->msg_type) {
 	case GSM411_MT_CP_DATA:
@@ -179,7 +172,7 @@
 
 	DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
 
-	return gsm411_sendmsg(msg, trans->sms.link_id);
+	return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id);
 }
 
 /* Prefix msg with a RP-DATA header and send as CP-DATA */
@@ -511,9 +504,8 @@
 
 /* process an incoming TPDU (called from RP-DATA) 
  * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ 
-static int gsm340_rx_tpdu(struct msgb *msg)
+static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
-	struct gsm_bts *bts = msg->lchan->ts->trx->bts;
 	u_int8_t *smsp = msgb_sms(msg);
 	struct gsm_sms *gsms;
 	u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
@@ -522,7 +514,7 @@
 	u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
 	int rc = 0;
 
-	counter_inc(bts->network->stats.sms.submitted);
+	counter_inc(conn->bts->network->stats.sms.submitted);
 
 	gsms = sms_alloc();
 	if (!gsms)
@@ -594,7 +586,7 @@
 		}
 	}
 
-	gsms->sender = subscr_get(msg->lchan->subscr);
+	gsms->sender = subscr_get(msg->lchan->conn.subscr);
 
 	LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
 	     "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
@@ -610,10 +602,10 @@
 	dispatch_signal(SS_SMS, 0, gsms);
 
 	/* determine gsms->receiver based on dialled number */
-	gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
+	gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr);
 	if (!gsms->receiver) {
 		rc = 1; /* cause 1: unknown subscriber */
-		counter_inc(bts->network->stats.sms.no_receiver);
+		counter_inc(conn->bts->network->stats.sms.no_receiver);
 		goto out;
 	}
 
@@ -687,7 +679,7 @@
 
 	DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
 
-	rc = gsm340_rx_tpdu(msg);
+	rc = gsm340_rx_tpdu(trans->conn, msg);
 	if (rc == 0)
 		return gsm411_send_rp_ack(trans, rph->msg_ref);
 	else if (rc > 0)
@@ -753,14 +745,17 @@
 	trans->sms.sms = NULL;
 
 	/* check for more messages for this subscriber */
-	sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
+	assert(msg->lchan->conn.subscr == trans->subscr);
+
+	sms = db_sms_get_unsent_for_subscr(trans->subscr);
 	if (sms)
-		gsm411_send_sms_lchan(msg->lchan, sms);
+		gsm411_send_sms_lchan(trans->conn, sms);
 
 	/* free the transaction here */
 	trans_free(trans);
 
 	/* release channel if done */
+#warning "BROKEN. The SAPI will be released automatically by the BSC"
 	if (!sms)
 		rsl_release_request(msg->lchan, trans->sms.link_id);
 
@@ -770,7 +765,7 @@
 static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
 			      struct gsm411_rp_hdr *rph)
 {
-	struct gsm_network *net = trans->lchan->ts->trx->bts->network;
+	struct gsm_network *net = trans->conn->bts->network;
 	struct gsm_sms *sms = trans->sms.sms;
 	u_int8_t cause_len = rph->data[0];
 	u_int8_t cause = rph->data[1];
@@ -780,7 +775,7 @@
 	 * the cause and take action depending on it */
 
 	LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
-	     subscr_name(msg->lchan->subscr), cause_len, cause,
+	     subscr_name(trans->conn->subscr), cause_len, cause,
 	     get_value_string(rp_cause_strs, cause));
 
 	if (!trans->sms.is_mt) {
@@ -833,11 +828,13 @@
 	dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
 
 	/* check for more messages for this subscriber */
-	sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
+	assert(msg->lchan->conn.subscr == trans->subscr);
+	sms = db_sms_get_unsent_for_subscr(trans->subscr);
 	if (sms)
-		gsm411_send_sms_lchan(msg->lchan, sms);
+		gsm411_send_sms_lchan(trans->conn, sms);
 	else
 		rsl_release_request(msg->lchan, trans->sms.link_id);
+#warning "BROKEN: The SAPI=3 will be released automatically by the BSC"
 
 	return rc;
 }
@@ -920,16 +917,16 @@
 	struct gsm_trans *trans;
 	int rc = 0;
 
-	if (!lchan->subscr)
+	if (!lchan->conn.subscr)
 		return -EIO;
 		/* FIXME: send some error message */
 
 	DEBUGP(DSMS, "trans_id=%x ", transaction_id);
-	trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
+	trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS,
 				 transaction_id);
 	if (!trans) {
 		DEBUGPC(DSMS, "(new) ");
-		trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
+		trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
 				    transaction_id, new_callref++);
 		if (!trans) {
 			DEBUGPC(DSMS, "No memory for trans\n");
@@ -941,8 +938,8 @@
 		trans->sms.is_mt = 0;
 		trans->sms.link_id = link_id;
 
-		trans->lchan = lchan;
-		use_lchan(lchan);
+		trans->conn = &lchan->conn;
+		use_subscr_con(trans->conn);
 	}
 
 	switch(msg_type) {
@@ -961,7 +958,7 @@
 				if (i == transaction_id)
 					continue;
 
-				ptrans = trans_find_by_id(lchan->subscr,
+				ptrans = trans_find_by_id(lchan->conn.subscr,
 				                          GSM48_PDISC_SMS, i);
 				if (!ptrans)
 					continue;
@@ -1041,7 +1038,7 @@
 /* Take a SMS in gsm_sms structure and send it through an already
  * existing lchan. We also assume that the caller ensured this lchan already
  * has a SAPI3 RLL connection! */
-int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
+int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
 {
 	struct msgb *msg = gsm411_msgb_alloc();
 	struct gsm_trans *trans;
@@ -1050,18 +1047,16 @@
 	int transaction_id;
 	int rc;
 
-	transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0);
+	transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
 	if (transaction_id == -1) {
 		LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
 		return -EBUSY;
 	}
 
-	msg->lchan = lchan;
-
 	DEBUGP(DSMS, "send_sms_lchan()\n");
 
 	/* FIXME: allocate transaction with message reference */
-	trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
+	trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
 			    transaction_id, new_callref++);
 	if (!trans) {
 		LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
@@ -1074,8 +1069,8 @@
 	trans->sms.sms = sms;
 	trans->sms.link_id = UM_SAPI_SMS;	/* FIXME: main or SACCH ? */
 
-	trans->lchan = lchan;
-	use_lchan(lchan);
+	trans->conn = conn;
+	use_subscr_con(trans->conn);
 
 	/* Hardcode SMSC Originating Address for now */
 	data = (u_int8_t *)msgb_put(msg, 8);
@@ -1112,7 +1107,7 @@
 
 	DEBUGP(DSMS, "TX: SMS DELIVER\n");
 
-	counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered);
+	counter_inc(conn->bts->network->stats.sms.delivered);
 
 	return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
 	/* FIXME: enter 'wait for RP-ACK' state, start TR1N */
@@ -1130,11 +1125,13 @@
 
 	switch (type) {
 	case BSC_RLLR_IND_EST_CONF:
-		gsm411_send_sms_lchan(lchan, sms);
+#warning "BROKEN: The BSC will establish this transparently"
+		gsm411_send_sms_lchan(&lchan->conn, sms);
 		break;
 	case BSC_RLLR_IND_REL_IND:
 	case BSC_RLLR_IND_ERR_IND:
 	case BSC_RLLR_IND_TIMEOUT:
+#warning "BROKEN: We will need to handle SAPI n Reject"
 		sms_free(sms);
 		break;
 	}
diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c
index dee89c0..40c3bbd 100644
--- a/openbsc/src/gsm_subscriber_base.c
+++ b/openbsc/src/gsm_subscriber_base.c
@@ -187,6 +187,7 @@
 
 void subscr_put_channel(struct gsm_lchan *lchan)
 {
+	struct gsm_subscriber_connection *conn = &lchan->conn;
 	/*
 	 * FIXME: Continue with other requests now... by checking
 	 * the gsm_subscriber inside the gsm_lchan. Drop the ref count
@@ -205,9 +206,9 @@
 	 * will listen to the paging requests before we timeout
 	 */
 
-	put_lchan(lchan);
+	put_subscr_con(conn);
 
-	if (lchan->subscr && !llist_empty(&lchan->subscr->requests))
-		subscr_send_paging_request(lchan->subscr);
+	if (lchan->conn.subscr && !llist_empty(&lchan->conn.subscr->requests))
+		subscr_send_paging_request(lchan->conn.subscr);
 }
 
diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c
index bd4c563..7fb0b13 100644
--- a/openbsc/src/handover_logic.c
+++ b/openbsc/src/handover_logic.c
@@ -122,7 +122,7 @@
 	new_lchan->bs_power = old_lchan->bs_power;
 	new_lchan->rsl_cmode = old_lchan->rsl_cmode;
 	new_lchan->tch_mode = old_lchan->tch_mode;
-	new_lchan->subscr = subscr_get(old_lchan->subscr);
+	new_lchan->conn.subscr = subscr_get(old_lchan->conn.subscr);
 
 	/* FIXME: do we have a better idea of the timing advance? */
 	rc = rsl_chan_activate_lchan(new_lchan, RSL_ACT_INTER_ASYNC, 0,
@@ -218,7 +218,7 @@
 	}
 
 	LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN "
-	     "%u->%u\n", subscr_name(ho->old_lchan->subscr),
+	     "%u->%u\n", subscr_name(ho->old_lchan->conn.subscr),
 	     ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr,
 	     ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn);
 
@@ -227,7 +227,7 @@
 	bsc_del_timer(&ho->T3103);
 
 	/* update lchan pointer of transaction */
-	trans_lchan_change(ho->old_lchan, new_lchan);
+	trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn);
 
 	ho->old_lchan->state = LCHAN_S_INACTIVE;
 	lchan_auto_release(ho->old_lchan);
@@ -243,6 +243,7 @@
 /* GSM 04.08 HANDOVER FAIL has been received */
 static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
 {
+	struct gsm_subscriber_connection *conn;
 	struct gsm_network *net = old_lchan->ts->trx->bts->network;
 	struct bsc_handover *ho;
 
@@ -256,7 +257,8 @@
 
 	bsc_del_timer(&ho->T3103);
 	llist_del(&ho->list);
-	put_lchan(ho->new_lchan);
+	conn = &ho->new_lchan->conn;
+	put_subscr_con(conn);
 	talloc_free(ho);
 
 	return 0;
diff --git a/openbsc/src/mncc.c b/openbsc/src/mncc.c
index 01d59aa..afd5364 100644
--- a/openbsc/src/mncc.c
+++ b/openbsc/src/mncc.c
@@ -332,16 +332,16 @@
 	remote_trans = trans_find_by_callref(call->net, call->remote_ref);
 
 	/* this shouldn't really happen */
-	if (!remote_trans || !remote_trans->lchan) {
+	if (!remote_trans || !remote_trans->conn) {
 		LOGP(DMNCC, LOGL_ERROR, "No transaction or transaction without lchan?!?\n");
 		return -EIO;
 	}
 
 	/* RTP socket of remote end has meanwhile died */
-	if (!remote_trans->lchan->abis_ip.rtp_socket)
+	if (!remote_trans->conn->lchan->abis_ip.rtp_socket)
 		return -EIO;
 
-	return rtp_send_frame(remote_trans->lchan->abis_ip.rtp_socket, dfr);
+	return rtp_send_frame(remote_trans->conn->lchan->abis_ip.rtp_socket, dfr);
 }
 
 
diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c
index cada24e..8bd5341 100644
--- a/openbsc/src/silent_call.c
+++ b/openbsc/src/silent_call.c
@@ -38,6 +38,7 @@
 static int paging_cb_silent(unsigned int hooknum, unsigned int event,
 			    struct msgb *msg, void *_lchan, void *_data)
 {
+	struct gsm_subscriber_connection *conn;
 	struct gsm_lchan *lchan = _lchan;
 	struct scall_signal_data sigdata;
 	int rc;
@@ -47,6 +48,8 @@
 
 	DEBUGP(DSMS, "paging_cb_silent: ");
 
+	conn = &lchan->conn;
+
 	sigdata.lchan = lchan;
 	sigdata.data = _data;
 
@@ -54,10 +57,10 @@
 	case GSM_PAGING_SUCCEEDED:
 		DEBUGPC(DSMS, "success, using Timeslot %u on ARFCN %u\n",
 			lchan->ts->nr, lchan->ts->trx->arfcn);
-		lchan->silent_call = 1;
+		conn->silent_call = 1;
 		/* increment lchan reference count */
 		dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
-		use_lchan(lchan);
+		use_subscr_con(conn);
 		break;
 	case GSM_PAGING_EXPIRED:
 		DEBUGP(DSMS, "expired\n");
@@ -97,7 +100,7 @@
 	int i;
 
 	/* if we're not part of a silent call, never reroute */
-	if (!msg->lchan->silent_call)
+	if (!msg->lchan->conn.silent_call)
 		return 0;
 
 	/* check if we are a special message that is handled in openbsc */
@@ -126,16 +129,18 @@
 int gsm_silent_call_stop(struct gsm_subscriber *subscr)
 {
 	struct gsm_lchan *lchan;
+	struct gsm_subscriber_connection *conn;
 
 	lchan = lchan_for_subscr(subscr);
 	if (!lchan)
 		return -EINVAL;
 
 	/* did we actually establish a silent call for this guy? */
-	if (!lchan->silent_call)
+	conn = &lchan->conn;
+	if (!conn->silent_call)
 		return -EINVAL;
 
-	put_lchan(lchan);
+	put_subscr_con(conn);
 
 	return 0;
 }
diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c
index 75a279d..5e0d507 100644
--- a/openbsc/src/transaction.c
+++ b/openbsc/src/transaction.c
@@ -95,10 +95,10 @@
 		break;
 	}
 
-	if (trans->lchan)
-		put_lchan(trans->lchan);
+	if (trans->conn)
+		put_subscr_con(trans->conn);
 
-	if (!trans->lchan && trans->subscr && trans->subscr->net) {
+	if (!trans->conn && trans->subscr && trans->subscr->net) {
 		/* Stop paging on all bts' */
 		paging_request_stop(NULL, trans->subscr, NULL);
 	}
@@ -148,21 +148,22 @@
 
 /* update all transactions to use a different LCHAN, e.g.
  * after handover has succeeded */
-int trans_lchan_change(struct gsm_lchan *lchan_old,
-		       struct gsm_lchan *lchan_new)
+int trans_lchan_change(struct gsm_subscriber_connection *conn_old,
+		       struct gsm_subscriber_connection *conn_new)
 {
-	struct gsm_network *net = lchan_old->ts->trx->bts->network;
+	struct gsm_network *net = conn_old->lchan->ts->trx->bts->network;
 	struct gsm_trans *trans;
 	int num = 0;
 
 	llist_for_each_entry(trans, &net->trans_list, entry) {
-		if (trans->lchan == lchan_old) {
-			/* drop old channel use cound */
-			put_lchan(trans->lchan);
+		if (trans->conn == conn_old) {
+
+			/* drop old channel use count */
+			put_subscr_con(conn_old);
 			/* assign new channel */
-			trans->lchan = lchan_new;
+			trans->conn = conn_new;
 			/* bump new channel use count */
-			use_lchan(trans->lchan);
+			use_subscr_con(conn_new);
 			num++;
 		}
 	}
diff --git a/openbsc/src/ussd.c b/openbsc/src/ussd.c
index a3d11f0..5476919 100644
--- a/openbsc/src/ussd.c
+++ b/openbsc/src/ussd.c
@@ -62,7 +62,7 @@
 /* A network-specific handler function */
 static int send_own_number(const struct msgb *msg, const struct ussd_request *req)
 {
-	char *own_number = msg->lchan->subscr->extension;
+	char *own_number = msg->lchan->conn.subscr->extension;
 	char response_string[GSM_EXTENSION_LENGTH + 20];
 
 	/* Need trailing CR as EOT character */
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index e894869..6dbae8c 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -601,16 +601,16 @@
 		lchan->nr, lchan->ts->nr, lchan->ts->trx->nr, 
 		lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
 		VTY_NEWLINE);
-	vty_out(vty, "  Use Count: %u, State: %s%s", lchan->use_count,
+	vty_out(vty, "  Use Count: %u, State: %s%s", lchan->conn.use_count,
 		gsm_lchans_name(lchan->state), VTY_NEWLINE);
 	vty_out(vty, "  BS Power: %u dBm, MS Power: %u dBm%s",
 		lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red
 		- lchan->bs_power*2,
 		ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power),
 		VTY_NEWLINE);
-	if (lchan->subscr) {
+	if (lchan->conn.subscr) {
 		vty_out(vty, "  Subscriber:%s", VTY_NEWLINE);
-		subscr_dump_vty(vty, lchan->subscr);
+		subscr_dump_vty(vty, lchan->conn.subscr);
 	} else
 		vty_out(vty, "  No Subscriber%s", VTY_NEWLINE);
 	if (is_ipaccess_bts(lchan->ts->trx->bts)) {