this is the first version that actually talks to the BTS
* initialize OML and RSL based on TEI establish (ACTIVATE_IND) events
* fix abis_nm_raw_msg() to not overwrite the OML header with payload
* fix debug print statements
* fix msgb_dequeue: actually dequeue it from the list ;)

diff --git a/src/abis_nm.c b/src/abis_nm.c
index bf442fa..e1a641b 100644
--- a/src/abis_nm.c
+++ b/src/abis_nm.c
@@ -138,7 +138,7 @@
 /* Send a OML NM Message from BSC to BTS */
 int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
 {
-	/* FIXME */
+	return _abis_nm_sendmsg(msg);
 }
 
 /* Receive a OML NM Message from BTS */
@@ -149,10 +149,12 @@
 
 	/* check for unsolicited message */
 	if (is_report(mt)) {
-		nmh->cfg->report_cb(mb, foh);
+		DEBUGP(DNM, "reporting NM MT 0x%02x\n", mt);
+		//nmh->cfg->report_cb(mb, foh);
 		return 0;
 	}
 
+#if 0
 	/* check if last message is to be acked */
 	if (is_ack_nack(nmh->last_msgtype)) {
 		if (mt == MT_ACK(nmh->last_msgtype)) {
@@ -169,6 +171,9 @@
 			return -EINVAL;
 		}
 	}
+#endif
+
+	return 0;
 }
 
 /* High-Level API */
@@ -198,7 +203,7 @@
 	if (oh->length + sizeof(*oh) < l2_len)
 		fprintf(stderr, "ABIS OML message with extra trailer?!?\n");
 
-	msg->l3_off = ((unsigned char *)oh + sizeof(*oh)) - msg->head;
+	msg->l3h = (unsigned char *)oh + sizeof(*oh);
 
 	switch (oh->mdisc) {
 	case ABIS_OM_MDISC_FOM:
@@ -213,6 +218,7 @@
 		return -EINVAL;
 	}
 
+	msgb_free(msg);
 	return rc;
 }
 
@@ -389,7 +395,7 @@
 	oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh));
 	fill_om_hdr(oh, len);
 	data = msgb_put(msg, len);
-	memcpy(msg->data, rawmsg, len);
+	memcpy(data, rawmsg, len);
 
 	return abis_nm_sendmsg(bts, msg);
 }
@@ -420,7 +426,7 @@
 	return __simple_cmd(bts, 0x74);
 }
 
-int abis_nm_db_transaction(struct gsm_bts *bts, int begin)
+int abis_nm_db_transmission(struct gsm_bts *bts, int begin)
 {
 	if (begin)
 		return __simple_cmd(bts, 0xA3);
diff --git a/src/abis_rsl.c b/src/abis_rsl.c
index ad90dea..257b118 100644
--- a/src/abis_rsl.c
+++ b/src/abis_rsl.c
@@ -618,13 +618,13 @@
 	case RSL_MT_DATA_IND:
 		DEBUGP(DRLL, "DATA INDICATION\n");
 		/* FIXME: Verify L3 info element */
-		msg->l3_off = &rllh->data[2] - msg->data;
+		msg->l3h = &rllh->data[2];
 		rc = gsm0408_rcvmsg(msg);
 		break;
 	case RSL_MT_EST_IND:
 		DEBUGP(DRLL, "ESTABLISH INDICATION\n");
 		/* FIXME: Verify L3 info element */
-		msg->l3_off = &rllh->data[2] - msg->data;
+		msg->l3h = &rllh->data[2];
 		rc = gsm0408_rcvmsg(msg);
 		break;
 	case RSL_MT_ERROR_IND:
diff --git a/src/bsc_hack.c b/src/bsc_hack.c
index 253826a..b0d7265 100644
--- a/src/bsc_hack.c
+++ b/src/bsc_hack.c
@@ -25,8 +25,10 @@
 #include <stdarg.h>
 #include <time.h>
 #include <string.h>
+#include <errno.h>
 
 #include <openbsc/gsm_data.h>
+#include <openbsc/select.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/abis_nm.h>
 
@@ -242,6 +244,8 @@
 {
 	struct gsm_bts_trx *trx = &bts->trx[0];
 
+	fprintf(stdout, "bootstrapping OML\n");
+
 	/* stop sending event reports */
 	abis_nm_event_reports(bts, 0);
 
@@ -510,6 +514,8 @@
 	}
 	rsl_sacch_filling(bts, RSL_SYSTEM_INFO_5, si5, sizeof(si5));
 	rsl_sacch_filling(bts, RSL_SYSTEM_INFO_6, si6, sizeof(si6));
+
+	return 0;
 }
 
 static void activate_traffic_channels(struct gsm_bts_trx *trx)
@@ -521,28 +527,47 @@
 		rsl_chan_activate_tch_f(&trx->ts[i]);
 }
 
-static void bootstrap_bts(struct gsm_bts *bts)
+static void bootstrap_rsl(struct gsm_bts *bts)
 {
-	bootstrap_om(bts);
-
+	fprintf(stdout, "bootstrapping RSL\n");
 	set_system_infos(bts);
 
 	/* FIXME: defer this until the channels are used */
 	activate_traffic_channels(&bts->trx[0]);
 }
 
-static void bootstrap_network()
+static void mi_cb(int event, struct gsm_bts *bts)
+{
+	switch (event) {
+	case EVT_E1_OML_UP:
+		bootstrap_om(bts);
+		break;
+	case EVT_E1_RSL_UP:
+		bootstrap_rsl(bts);
+		break;
+	default:
+		/* FIXME: deal with TEI or L1 link loss */
+		break;
+	}
+}
+
+static int bootstrap_network(void)
 {
 	struct gsm_bts *bts;
 
 	/* initialize our data structures */
 	gsmnet = gsm_network_init(1, 1, 1);
+	if (!gsmnet)
+		return -ENOMEM;
+		
 	bts = &gsmnet->bts[0];
 	bts->location_area_code = 1;
 	bts->trx[0].arfcn = HARDCODED_ARFCN;
 
-	/* initialize the BTS */
-	bootstrap_bts(&gsmnet->bts[0]);
+	if (mi_setup(bts, 0, mi_cb) < 0)
+		return -EIO;
+
+	return 0;
 }
 
 void debugp(int subsys, char *file, int line, const char *format, ...)
@@ -558,16 +583,15 @@
 	timestr = ctime(&tm);
 	timestr[strlen(timestr)-1] = '\0';
 	fprintf(outfd, "%s <%4.4x> %s:%d ", timestr, subsys, file, line);
-	vsprintf(outfd, format, ap);
+	vfprintf(outfd, format, ap);
+
 	va_end(ap);
+
 	fflush(outfd);
 }
 
 int main(int argc, char **argv)
 {
-	if (mi_setup() < 0)
-		exit(1);
-
 	bootstrap_network();
 
 	while (1) {
diff --git a/src/misdn.c b/src/misdn.c
index 8f9aed8..10a92d1 100644
--- a/src/misdn.c
+++ b/src/misdn.c
@@ -57,6 +57,7 @@
 	struct llist_head rsl_tx_list;
 	struct llist_head oml_tx_list;
 
+	void (*cb)(int event, struct gsm_bts *bts);
 	struct bsc_fd fd[NUM_E1_TS];
 };
 
@@ -65,7 +66,7 @@
 
 #define SAPI_L2ML	0
 #define SAPI_OML	62
-#define SAPI_RSL	63
+#define SAPI_RSL	0	/* 63 ? */
 
 #define TEI_L2ML	127
 #define TEI_OML		25
@@ -149,17 +150,32 @@
 		DEBUGP(DMI, "got DL_ESTABLISH_CNF\n");
 		break;
 	case DL_RELEASE_IND:
-		DEBUGP(DMI, "got DL_RELEASE_IND\n");
+		DEBUGP(DMI, "got DL_RELEASE_IND: E1 Layer 1 disappeared?\n");
 		break;
 	case MPH_ACTIVATE_IND:
 		DEBUGP(DMI, "got MPH_ACTIVATE_IND\n");
+		if (l2addr.tei == TEI_OML && l2addr.sapi == SAPI_OML)
+			e1h->cb(EVT_E1_OML_UP, e1h->bts);
+		else if (l2addr.tei == TEI_RSL && l2addr.sapi == SAPI_RSL)
+			e1h->cb(EVT_E1_RSL_UP, e1h->bts);
 		break;
 	case MPH_DEACTIVATE_IND:
-		DEBUGP(DMI, "got MPH_DEACTIVATE_IND\n");
+		DEBUGP(DMI, "got MPH_DEACTIVATE_IND: TEI link closed?\n");
+		if (l2addr.tei == TEI_OML && l2addr.sapi == SAPI_OML)
+			e1h->cb(EVT_E1_OML_DN, e1h->bts);
+		else if (l2addr.tei == TEI_RSL && l2addr.sapi == SAPI_RSL)
+			e1h->cb(EVT_E1_RSL_DN, e1h->bts);
+		break;
 		break;
 	case DL_DATA_IND:
 		DEBUGP(DMI, "got DL_DATA_IND\n");
-		msg->l2_off = MISDN_HEADER_LEN;
+
+		/* FIXME: this stinks */
+		msg->trx = e1h->bts->c0;
+
+		msg->l2h = msg->data + MISDN_HEADER_LEN;
+		
+		fprintf(stdout, "RX: ");
 		hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN);
 		switch (l2addr.tei) {
 		case TEI_OML:
@@ -185,31 +201,44 @@
 	struct mi_e1_handle *e1h = bfd->data;
 	struct msgb *msg;
 	struct mISDNhead *hh;
-	int ret, no_rsl = 0;
+	int ret, no_oml = 0;
 
-	msg = msgb_dequeue(&e1h->rsl_tx_list);
+	msg = msgb_dequeue(&e1h->oml_tx_list);
 	if (!msg)
-		no_rsl = 1;
+		no_oml = 1;
 	else {
+		u_int8_t *l2_data = msg->data;
+
 		/* prepend the mISDNhead */
 		hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh));
 		hh->prim = DL_DATA_REQ;
 
+		fprintf(stdout, "OML TX: ");
+		hexdump(l2_data, msg->len - MISDN_HEADER_LEN);
+
 		ret = sendto(bfd->fd, msg->data, msg->len, 0,
 			     (struct sockaddr *)&e1h->l2addr,
 			     sizeof(e1h->l2addr));
 		msgb_free(msg);
 		usleep(100000);
+		/* we always dequeue all OML messages */
+		return ret;
 	}
+
 	msg = msgb_dequeue(&e1h->rsl_tx_list);
 	if (!msg) {
-		if (no_rsl)
+		if (no_oml)
 			bfd->when &= ~BSC_FD_WRITE;
 	} else {
+		u_int8_t *l2_data = msg->data;
+
 		/* prepend the mISDNhead */
 		hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh));
 		hh->prim = DL_DATA_REQ;
 
+		fprintf(stdout, "RSL TX: ");
+		hexdump(l2_data, msg->len - MISDN_HEADER_LEN);
+
 		ret = sendto(bfd->fd, msg->data, msg->len, 0,
 			     (struct sockaddr *)&e1h->omladdr,
 			     sizeof(e1h->omladdr));
@@ -258,16 +287,18 @@
 {
 	struct mi_e1_handle *e1h = global_e1h;
 
+	msg->l2h = msg->data;
 	msgb_enqueue(&e1h->rsl_tx_list, msg);
 	e1h->fd[0].when |= BSC_FD_WRITE;
 
 	return 0;
 }
 
-int abis_nm_sendmsg(struct msgb *msg)
+int _abis_nm_sendmsg(struct msgb *msg)
 {
 	struct mi_e1_handle *e1h = global_e1h;
 
+	msg->l2h = msg->data;
 	msgb_enqueue(&e1h->oml_tx_list, msg);
 	e1h->fd[0].when |= BSC_FD_WRITE;
 
@@ -292,13 +323,14 @@
 		close(sk);
 		return -ENODEV;
 	}
-	DEBUGP(DMI,"%d device%s found\n", cnt, (cnt==1)?"":"s");
-#if 0
-	devinfo.id = di->cardnr;
+	//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;
 	ret = ioctl(sk, IMGETDEVINFO, &devinfo);
 	if (ret < 0) {
 		fprintf(stdout, "error getting info for device %d: %s\n",
-			di->cardnr, strerror(errno));
+			e1h->cardnr, strerror(errno));
 		return -ENODEV;
 	}
 	fprintf(stdout, "        id:             %d\n", devinfo.id);
@@ -320,7 +352,7 @@
 		bfd->cb = misdn_fd_cb;
 
 		if (ts == 1) {
-			bfd->fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_LAPD_NT);
+			bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_NT);
 			bfd->when = BSC_FD_READ;
 		} else
 			bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
@@ -360,7 +392,8 @@
 	return 0;
 }
 
-int mi_setup(struct gsm_bts *bts, int cardnr)
+int mi_setup(struct gsm_bts *bts, int cardnr, 
+	     void (cb)(int event, struct gsm_bts *bts))
 {
 	struct mi_e1_handle *e1h;
 
@@ -369,6 +402,7 @@
 
 	e1h->cardnr = cardnr;
 	e1h->bts = bts;
+	e1h->cb = cb;
 	INIT_LLIST_HEAD(&e1h->oml_tx_list);
 	INIT_LLIST_HEAD(&e1h->rsl_tx_list);
 
diff --git a/src/msgb.c b/src/msgb.c
index f5330c3..249fed9 100644
--- a/src/msgb.c
+++ b/src/msgb.c
@@ -62,6 +62,7 @@
 		return NULL;
 
 	lh = queue->next;
-
+	llist_del(lh);
+	
 	return llist_entry(lh, struct msgb, list);
 }