Merge branch 'master' of git.osmocom.org:openbsc
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index 37011a1..d0c85ea 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -31,8 +31,8 @@
 
 /* one time initialisation */
 int db_init(const char *name);
-int db_prepare();
-int db_fini();
+int db_prepare(void);
+int db_fini(void);
 
 /* subscriber management */
 struct gsm_subscriber *db_create_subscriber(struct gsm_network *net,
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
index ff4aec1..d78252a 100644
--- a/openbsc/include/openbsc/debug.h
+++ b/openbsc/include/openbsc/debug.h
@@ -35,6 +35,7 @@
 	DLLC,
 	DSNDCP,
 	DNAT,
+	DCTRL,
 	Debug_LastEntry,
 };
 
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 5023d06..62fbb85 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -78,7 +78,7 @@
 	/* CKSN */
 	enum gprs_ciph_algo	ciph_algo;
 	struct {
-		uint8_t	buf[14];	/* 10.5.5.12a */
+		uint8_t	buf[52];	/* 10.5.5.12a */
 		uint8_t	len;
 	} ms_radio_access_capa;
 	struct {
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index b9b89e6..ec6c2c0 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -1,10 +1,11 @@
 #ifndef _GSM_04_08_H
 #define _GSM_04_08_H
 
-#include <openbsc/meas_rep.h>
-
-#include <osmocom/gsm/protocol/gsm_04_08.h>
 #include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include <openbsc/meas_rep.h>
 
 struct msgb;
 struct gsm_bts;
@@ -31,7 +32,8 @@
 int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);
 int gsm0408_new_conn(struct gsm_subscriber_connection *conn);
 enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, uint8_t ra);
-enum gsm_chreq_reason_t get_reason_by_chreq(uint8_t ra, int neci);
+/* don't use "enum gsm_chreq_reason_t" to avoid circular dependency */
+int get_reason_by_chreq(uint8_t ra, int neci);
 void gsm_net_update_ctype(struct gsm_network *net);
 
 int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn);
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index b9f8116..7c290c7 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -82,7 +82,7 @@
 typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
 typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
 typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
-typedef int (*mgcp_reset)(struct mgcp_config *cfg);
+typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
 
 #define PORT_ALLOC_STATIC	0
 #define PORT_ALLOC_DYNAMIC	1
diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h
index 3212b36..59b75c3 100644
--- a/openbsc/include/openbsc/osmo_msc_data.h
+++ b/openbsc/include/openbsc/osmo_msc_data.h
@@ -65,7 +65,7 @@
 	char *mid_call_txt;
 	int mid_call_timeout;
 	char *rf_ctrl_name;
-	struct osmo_bsc_rf *rf_ctl;
+	struct osmo_bsc_rf *rf_ctrl;
 
 	/* ussd welcome text */
 	char *ussd_welcome_txt;
diff --git a/openbsc/include/openbsc/paging.h b/openbsc/include/openbsc/paging.h
index 0872eb8..e1438ba 100644
--- a/openbsc/include/openbsc/paging.h
+++ b/openbsc/include/openbsc/paging.h
@@ -68,4 +68,6 @@
 /* pending paging requests */
 unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
 
+void *paging_get_data(struct gsm_bts *bts, struct gsm_subscriber *subscr);
+
 #endif
diff --git a/openbsc/src/gprs/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c
index 028f989..ee8a870 100644
--- a/openbsc/src/gprs/gb_proxy_main.c
+++ b/openbsc/src/gprs/gb_proxy_main.c
@@ -36,7 +36,6 @@
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/select.h>
 #include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/process.h>
 
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 46c4931..098e4c2 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -675,8 +675,9 @@
 	/* MS Radio Access Capability 10.5.5.12a */
 	ms_ra_acc_cap_len = *cur++;
 	ms_ra_acc_cap = cur;
-	if (ms_ra_acc_cap_len > 51)
+	if (ms_ra_acc_cap_len > 52)
 		goto err_inval;
+	cur += ms_ra_acc_cap_len;
 
 	/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
 
@@ -735,8 +736,10 @@
 	ctx->cell_id = cid;
 	/* Update MM Context with other data */
 	ctx->drx_parms = drx_par;
-	ctx->ms_radio_access_capa.len = ms_ra_acc_cap_len;
-	memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap, ms_ra_acc_cap_len);
+	ctx->ms_radio_access_capa.len = OSMO_MIN(ms_ra_acc_cap_len,
+					 sizeof((ctx->ms_radio_access_capa.buf)));
+	memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap,
+		ctx->ms_radio_access_capa.len);
 	ctx->ms_network_capa.len = msnc_len;
 	memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
 
@@ -754,7 +757,7 @@
 			  GPRS_ALGO_GEA0, NULL);
 
 	DEBUGPC(DMM, "\n");
-	return ctx ? gsm48_gmm_authorize(ctx, GMM_T3350_MODE_ATT) : 0;
+	return gsm48_gmm_authorize(ctx, GMM_T3350_MODE_ATT);
 
 err_inval:
 	DEBUGPC(DMM, "\n");
@@ -910,6 +913,9 @@
 	/* MS Radio Access Capability 10.5.5.12a */
 	ms_ra_acc_cap_len = *cur++;
 	ms_ra_acc_cap = cur;
+	if (ms_ra_acc_cap_len > 52)
+		return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
+	cur += ms_ra_acc_cap_len;
 
 	/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
 	 * DRX parameter, MS network capability */
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index f7408ef..7d4ed51 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -696,7 +696,7 @@
 			struct gprs_llc_llme *llme;
 			/* FIXME: don't use the TLLI but the 0xFFFF unassigned? */
 			llme = llme_alloc(msgb_tlli(msg));
-			LOGP(DLLC, LOGL_DEBUG, "LLC RX: unknown TLLI 0x08x, "
+			LOGP(DLLC, LOGL_DEBUG, "LLC RX: unknown TLLI 0x%08x, "
 				"creating LLME on the fly\n", msgb_tlli(msg));
 			lle = &llme->lle[llhp.sapi];
 		} else {
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index f193aa3..71694a4 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -500,8 +500,6 @@
 	rate_ctr_add(&mmctx->ctrg->ctr[GMM_CTR_BYTES_UDATA_IN], npdu_len);
 
 	return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
-
-	return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
 }
 
 /* libgtp select loop integration */
diff --git a/openbsc/src/gprs/sgsn_main.c b/openbsc/src/gprs/sgsn_main.c
index bfa2e52..fa61e0e 100644
--- a/openbsc/src/gprs/sgsn_main.c
+++ b/openbsc/src/gprs/sgsn_main.c
@@ -281,5 +281,6 @@
 			exit(3);
 	}
 
+	/* not reached */
 	exit(0);
 }
diff --git a/openbsc/src/ipaccess/ipaccess-firmware.c b/openbsc/src/ipaccess/ipaccess-firmware.c
index 6d39107..5f55bb5 100644
--- a/openbsc/src/ipaccess/ipaccess-firmware.c
+++ b/openbsc/src/ipaccess/ipaccess-firmware.c
@@ -59,9 +59,9 @@
 	}
 
 	if (memcmp(firmware_header->more_magic, more_magic, 2) != 0) {
-		fprintf(stderr, "Wrong more magic. Got: 0x%x %x %x %x\n",
+		fprintf(stderr, "Wrong more magic. Got: 0x%x 0x%x vs. 0x%x 0x%x\n",
 			firmware_header->more_magic[0] & 0xff, firmware_header->more_magic[1] & 0xff,
-			firmware_header->more_magic[2] & 0xff, firmware_header->more_magic[3] & 0xff);
+			more_magic[0], more_magic[1]);
 		return -1;
 	}
 
diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c
index b4d17e2..1dd5b84 100644
--- a/openbsc/src/ipaccess/ipaccess-proxy.c
+++ b/openbsc/src/ipaccess/ipaccess-proxy.c
@@ -103,7 +103,7 @@
 	uint16_t gprs_orig_port;
 	uint32_t gprs_orig_ip;
 
-	char *id_tags[0xff];
+	char *id_tags[256];
 	uint8_t *id_resp;
 	unsigned int id_resp_len;
 };
@@ -488,7 +488,7 @@
 				return 0;
 			}
 
-			if (trx_id > MAX_TRX) {
+			if (trx_id >= MAX_TRX) {
 				LOGP(DINP, LOGL_ERROR, "We don't support more "
 				     "than %u TRX\n", MAX_TRX);
 				return -EINVAL;
@@ -1076,7 +1076,7 @@
 	}
 }
 
-static void print_help()
+static void print_help(void)
 {
 	printf(" ipaccess-proxy is a proxy BTS.\n");
 	printf(" -h --help. This help text.\n");
@@ -1090,7 +1090,7 @@
 	printf(" -V --version. Print the version of OpenBSC.\n");
 }
 
-static void print_usage()
+static void print_usage(void)
 {
 	printf("Usage: ipaccess-proxy [options]\n");
 }
diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c
index 494d4ca..49e86ba 100644
--- a/openbsc/src/libbsc/abis_nm.c
+++ b/openbsc/src/libbsc/abis_nm.c
@@ -776,7 +776,7 @@
 	char seg_buf[256];
 	char *line_buf = seg_buf+2;
 	unsigned char *tlv;
-	uint8_t len;
+	int len;
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
 
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index 8356bd9..d74907b 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -427,7 +427,7 @@
 	 */
 	msgb_v_put(msg, RSL_IE_CHAN_IDENT);
 	len = msgb_put(msg, 1);
-	msgb_tlv_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
+	msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
 
 	if (lchan->ts->hopping.enabled)
 		msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c
index 1be8cb7..02a3adf 100644
--- a/openbsc/src/libbsc/bsc_init.c
+++ b/openbsc/src/libbsc/bsc_init.c
@@ -406,6 +406,9 @@
 
 	bts->si_common.ncc_permitted = 0xff;
 
+	/* Initialize the BTS state */
+	gsm_bts_mo_reset(bts);
+
 	return 0;
 }
 
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index 971cdf7..26ed7d9 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -189,9 +189,9 @@
 	dump_pchan_load_vty(vty, "    ", &pl);
 
 	/* show rf */
-	if (net->msc_data && net->msc_data->rf_ctl)
+	if (net->msc_data && net->msc_data->rf_ctrl)
 		vty_out(vty, "  Last RF Command: %s%s",
-			net->msc_data->rf_ctl->last_state_command,
+			net->msc_data->rf_ctrl->last_state_command,
 			VTY_NEWLINE);
 }
 
@@ -1055,11 +1055,14 @@
 	}
 	if (argc >= 1) {
 		int num = atoi(argv[0]);
-		llist_for_each_entry(line, &e1inp_line_list, list) {
-			if (line->num == num)
+		struct e1inp_line *l;
+		llist_for_each_entry(l, &e1inp_line_list, list) {
+			if (l->num == num) {
+				line = l;
 				break;
+			}
 		}
-		if (!line || line->num != num) {
+		if (!line) {
 			vty_out(vty, "E1 line %s is invalid%s",
 				argv[0], VTY_NEWLINE);
 			return CMD_WARNING;
@@ -1067,7 +1070,7 @@
 	}	
 	if (argc >= 2) {
 		ts_nr = atoi(argv[1]);
-		if (ts_nr > NUM_E1_TS) {
+		if (ts_nr >= NUM_E1_TS) {
 			vty_out(vty, "E1 timeslot %s is invalid%s",
 				argv[1], VTY_NEWLINE);
 			return CMD_WARNING;
@@ -1157,7 +1160,7 @@
 
 DEFUN(cfg_net_mnc,
       cfg_net_mnc_cmd,
-      "mobile network code <1-999>",
+      "mobile network code <0-999>",
       "Set the GSM mobile network code")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c
index 17bce85..92335f2 100644
--- a/openbsc/src/libbsc/gsm_04_08_utils.c
+++ b/openbsc/src/libbsc/gsm_04_08_utils.c
@@ -190,7 +190,7 @@
 	return GSM_LCHAN_SDCCH;
 }
 
-enum gsm_chreq_reason_t get_reason_by_chreq(uint8_t ra, int neci)
+int get_reason_by_chreq(uint8_t ra, int neci)
 {
 	int i;
 	int length;
diff --git a/openbsc/src/libbsc/paging.c b/openbsc/src/libbsc/paging.c
index 4dfa921..fe60e3f 100644
--- a/openbsc/src/libbsc/paging.c
+++ b/openbsc/src/libbsc/paging.c
@@ -405,3 +405,17 @@
 
 	return requests;
 }
+
+/**
+ * Find any paging data for the given subscriber at the given BTS.
+ */
+void *paging_get_data(struct gsm_bts *bts, struct gsm_subscriber *subscr)
+{
+	struct gsm_paging_request *req;
+
+	llist_for_each_entry(req, &bts->paging.pending_requests, entry)
+		if (req->subscr == subscr)
+			return req->cbfn_param;
+
+	return NULL;
+}
diff --git a/openbsc/src/libcommon/debug.c b/openbsc/src/libcommon/debug.c
index 1372150..479390c 100644
--- a/openbsc/src/libcommon/debug.c
+++ b/openbsc/src/libcommon/debug.c
@@ -175,6 +175,11 @@
 		.description = "GSM 08.08 NAT/Multipkexer",
 		.enabled = 1, .loglevel = LOGL_NOTICE,
 	},
+	[DCTRL] = {
+		.name = "DCTRL",
+		.description = "Control interface",
+		.enabled = 1, .loglevel = LOGL_NOTICE,
+	},
 };
 
 enum log_filter {
diff --git a/openbsc/src/libcommon/gsm_data_shared.c b/openbsc/src/libcommon/gsm_data_shared.c
index 58e3bed..b52d58a 100644
--- a/openbsc/src/libcommon/gsm_data_shared.c
+++ b/openbsc/src/libcommon/gsm_data_shared.c
@@ -36,7 +36,6 @@
 
 void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
 {
-	mo->nm_state.administrative = NM_STATE_NULL;
 	mo->nm_state.operational = NM_OPSTATE_NULL;
 	mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
 }
diff --git a/openbsc/src/libctrl/control_if.c b/openbsc/src/libctrl/control_if.c
index 0e625cd..91c69e0 100644
--- a/openbsc/src/libctrl/control_if.c
+++ b/openbsc/src/libctrl/control_if.c
@@ -22,6 +22,7 @@
  */
 
 #include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -365,7 +366,7 @@
 		return NULL;
 
 	for (i=0;i<ctrg->desc->num_ctr;i++) {
-		counters = talloc_asprintf_append(counters, "\n%s.%u.%s %lu",
+		counters = talloc_asprintf_append(counters, "\n%s.%u.%s %"PRIu64,
 			ctrg->desc->group_name_prefix, ctrg->idx,
 			ctrg->desc->ctr_desc[i].name,
 			get_rate_ctr_value(&ctrg->ctr[i], intv));
diff --git a/openbsc/src/libgb/gprs_bssgp_util.c b/openbsc/src/libgb/gprs_bssgp_util.c
index b539323..a1eb37e 100644
--- a/openbsc/src/libgb/gprs_bssgp_util.c
+++ b/openbsc/src/libgb/gprs_bssgp_util.c
@@ -111,9 +111,8 @@
 		uint16_t _bvci = htons(*bvci);
 		msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
 	}
-	if (orig_msg)
-		msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR,
-			      msgb_bssgp_len(orig_msg), msgb_bssgph(orig_msg));
+	msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR,
+		      msgb_bssgp_len(orig_msg), msgb_bssgph(orig_msg));
 
 	return gprs_ns_sendmsg(bssgp_nsi, msg);
 }
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 1d26850..44a3b87 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -831,8 +831,20 @@
 
 static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg)
 {
+	struct mgcp_msg_ptr data_ptrs[6];
+	const char *trans_id;
+	struct mgcp_endpoint *endp;
+	int found;
+
+	found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs),
+				    &trans_id, &endp);
+	if (found != 0) {
+		LOGP(DMGCP, LOGL_ERROR, "Failed to find the endpoint.\n");
+		return NULL;
+	}
+
 	if (cfg->reset_cb)
-		cfg->reset_cb(cfg);
+		cfg->reset_cb(endp->tcfg);
 	return NULL;
 }
 
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 1ddd3fd..a7eeda4 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -221,7 +221,7 @@
 }
 
 
-int db_prepare()
+int db_prepare(void)
 {
 	dbi_result result;
 	int i;
@@ -245,15 +245,13 @@
 	return 0;
 }
 
-int db_fini()
+int db_fini(void)
 {
 	dbi_conn_close(conn);
 	dbi_shutdown();
 
-	if (db_dirname)
-	    free(db_dirname);
-	if (db_basename)
-	    free(db_basename);
+	free(db_dirname);
+	free(db_basename);
 	return 0;
 }
 
@@ -276,9 +274,9 @@
 	}
 
 	subscr = subscr_alloc();
-	subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
 	if (!subscr)
 		return NULL;
+	subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
 	result = dbi_conn_queryf(conn,
 		"INSERT INTO Subscriber "
 		"(imsi, created, updated) "
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index ba72c37..ee7f577 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -554,7 +554,8 @@
 {
 	uint8_t *smsp = msgb_sms(msg);
 	struct gsm_sms *gsms;
-	uint8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
+	unsigned int sms_alphabet;
+	uint8_t sms_mti, sms_mms, sms_vpf, sms_rp;
 	uint8_t *sms_vp;
 	uint8_t da_len_bytes;
 	uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
diff --git a/openbsc/src/libmsc/sms_queue.c b/openbsc/src/libmsc/sms_queue.c
index 30fa5f0..e685973 100644
--- a/openbsc/src/libmsc/sms_queue.c
+++ b/openbsc/src/libmsc/sms_queue.c
@@ -51,6 +51,8 @@
 	unsigned long long sms_id;
 	int failed_attempts;
 	int resend;
+
+	int no_detach;
 };
 
 struct gsm_sms_queue {
@@ -86,17 +88,24 @@
 	return sms_find_pending(smsq, sms) != NULL;
 }
 
-static int sms_subscriber_is_pending(struct gsm_sms_queue *smsq,
-				     struct gsm_subscriber *subscr)
+static struct gsm_sms_pending *sms_subscriber_find_pending(
+					struct gsm_sms_queue *smsq,
+					struct gsm_subscriber *subscr)
 {
 	struct gsm_sms_pending *pending;
 
 	llist_for_each_entry(pending, &smsq->pending_sms, entry) {
 		if (pending->subscr == subscr)
-			return 1;
+			return pending;
 	}
 
-	return 0;
+	return NULL;
+}
+
+static int sms_subscriber_is_pending(struct gsm_sms_queue *smsq,
+				     struct gsm_subscriber *subscr)
+{
+	return sms_subscriber_find_pending(smsq, subscr) != NULL;
 }
 
 static struct gsm_sms_pending *sms_pending_from(struct gsm_sms_queue *smsq,
@@ -146,7 +155,7 @@
 	if (++pending->failed_attempts < smsq->max_fail)
 		return sms_pending_resend(pending);
 
-	if (paging_error) {
+	if (paging_error && !pending->no_detach) {
 		LOGP(DSMS, LOGL_NOTICE,
 		     "Subscriber %llu is not reachable. Setting LAC=0.\n", pending->subscr->id);
 		pending->subscr->lac = GSM_LAC_RESERVED_DETACHED;
@@ -321,16 +330,41 @@
 	return 0;
 }
 
-static int sub_ready_for_sm(struct gsm_subscriber *subscr)
+static int sub_ready_for_sm(struct gsm_network *net, struct gsm_subscriber *subscr)
 {
-	struct gsm_subscriber_connection *conn;
 	struct gsm_sms *sms;
+	struct gsm_sms_pending *pending;
+	struct gsm_subscriber_connection *conn;
 
-	/* A subscriber has attached. Check if there are
-	 * any pending SMS for him to be delivered */
+	/*
+	 * The code used to be very clever and tried to submit
+	 * a SMS during the Location Updating Request. This has
+	 * two issues:
+	 *   1.) The Phone might not be ready yet, e.g. the C155
+	 *       will not respond to the Submit when it is booting.
+	 *   2.) The queue is already trying to submit SMS to the
+	 *	 user and by not responding to the paging request
+	 *	 we will set the LAC back to 0. We would have to
+	 *	 stop the paging and move things over.
+	 *
+	 * We need to be careful in what we try here.
+	 */
+
+	/* check if we have pending requests */
+	pending = sms_subscriber_find_pending(net->sms_queue, subscr);
+	if (pending) {
+		LOGP(DMSC, LOGL_NOTICE,
+		     "Pending paging while subscriber %llu attached.\n",
+		      subscr->id);
+		pending->no_detach = 1;
+		return 0;
+	}
+
 	conn = connection_for_subscr(subscr);
 	if (!conn)
 		return -1;
+
+	/* Now try to deliver any pending SMS to this sub */
 	sms = db_sms_get_unsent_for_subscr(subscr);
 	if (!sms)
 		return -1;
@@ -347,7 +381,7 @@
 		return 0;
 
 	/* this is readyForSM */
-	return sub_ready_for_sm(subscr);
+	return sub_ready_for_sm(handler_data, subscr);
 }
 
 static int sms_sms_cb(unsigned int subsys, unsigned int signal,
diff --git a/openbsc/src/libtrau/trau_frame.c b/openbsc/src/libtrau/trau_frame.c
index 15cbe4f..8fbaf86 100644
--- a/openbsc/src/libtrau/trau_frame.c
+++ b/openbsc/src/libtrau/trau_frame.c
@@ -140,8 +140,14 @@
 	case TRAU_FT_EFR:
 		/* clear time alignment */
 		memset(fr->c_bits+5, 0, 6);
-		/* FIXME: set UFE appropriately */
-		/* FIXME: SP / BFI in case of DTx */
+		/* set UFE appropriately */
+		fr->c_bits[11] = 1; /* C12 (UFE), good frame (TODO) */
+		/* C13 .. C15 are spare and coded as '1' */
+		memset(fr->c_bits+12, 0x01, 3);
+		/* SP / BFI in case of DTx */
+		fr->c_bits[15] = 1; /* C16 (SP), no DTX (TODO) */
+		/* C17 .. C21 are spare and coded as '1' */
+		memset(fr->c_bits+16, 0x01, 5);
 		break;
 	case TRAU_FT_IDLE_UP:
 		memcpy(fr->c_bits, ft_idle_down_bits, 5);
@@ -246,7 +252,7 @@
 	.t_bits = { 1, 1, 1, 1 },
 };
 static uint8_t encoded_idle_frame[TRAU_FRAME_BITS];
-static int dbits_initted;
+static int dbits_initted = 0;
 
 uint8_t *trau_idle_frame(void)
 {
@@ -254,7 +260,27 @@
 	if (!dbits_initted) {
 		/* set all D-bits to 1 */
 		memset(&fr_idle_frame.d_bits, 0x01, 260);
+
+		memset(&fr_idle_frame.c_bits, 0x01, 25); /* spare are set to 1 */
+		/* set Downlink Idle Speech Frame pattern */
+		fr_idle_frame.c_bits[0] = 0; /* C1 */
+		fr_idle_frame.c_bits[1] = 1; /* C2 */
+		fr_idle_frame.c_bits[2] = 1; /* C3 */
+		fr_idle_frame.c_bits[3] = 1; /* C4 */
+		fr_idle_frame.c_bits[4] = 0; /* C5 */
+		/* set no Time Alignment pattern */
+		fr_idle_frame.c_bits[5] = 0; /* C6 */
+		fr_idle_frame.c_bits[6] = 0; /* C7 */
+		fr_idle_frame.c_bits[7] = 0; /* C8 */
+		fr_idle_frame.c_bits[8] = 0; /* C9 */
+		fr_idle_frame.c_bits[9] = 0; /* C10 */
+		fr_idle_frame.c_bits[10] = 0; /* C11 */
+		/* already set to 1, but maybe we need to modify it in the future */
+		fr_idle_frame.c_bits[11] = 1; /* C12 (UFE), good frame */
+		fr_idle_frame.c_bits[15] = 1; /* C16 (SP), no DTX */
+
 		encode_fr(encoded_idle_frame, &fr_idle_frame);
+		dbits_initted = 1; /* set it to 1 to not call it again */
 	}
 	return encoded_idle_frame;
 }
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index 1a6d806..d02b0b5 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -24,6 +24,8 @@
 #include <osmocom/gsm/protocol/gsm_08_08.h>
 #include <osmocom/gsm/gsm0808.h>
 
+#include <osmocom/sccp/sccp.h>
+
 #define return_when_not_connected(conn) \
 	if (!conn->sccp_con) {\
 		LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
@@ -102,11 +104,13 @@
 				     conn->bts->cell_identity);
 	if (!resp) {
 		LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
+		sccp_connection_free(conn->sccp_con->sccp);
 		bsc_delete_connection(conn->sccp_con);
 		return BSC_API_CONN_POL_REJECT;
 	}
 
 	if (bsc_open_connection(conn->sccp_con, resp) != 0) {
+		sccp_connection_free(conn->sccp_con->sccp);
 		bsc_delete_connection(conn->sccp_con);
 		msgb_free(resp);
 		return BSC_API_CONN_POL_REJECT;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_grace.c b/openbsc/src/osmo-bsc/osmo_bsc_grace.c
index c67984b..fbc26ac 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_grace.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_grace.c
@@ -26,9 +26,9 @@
 
 int bsc_grace_allow_new_connection(struct gsm_network *network)
 {
-	if (!network->msc_data->rf_ctl)
+	if (!network->msc_data->rf_ctrl)
 		return 1;
-	return network->msc_data->rf_ctl->policy == S_RF_ON;
+	return network->msc_data->rf_ctrl->policy == S_RF_ON;
 }
 
 static int handle_sub(struct gsm_lchan *lchan, const char *text)
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_main.c b/openbsc/src/osmo-bsc/osmo_bsc_main.c
index 7d5d835..7d376ef 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_main.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_main.c
@@ -29,8 +29,8 @@
 #include <openbsc/ipaccess.h>
 
 #include <osmocom/core/application.h>
+#include <osmocom/core/linuxlist.h>
 #include <osmocom/core/talloc.h>
-#include <osmocom/core/process.h>
 #include <osmocom/gsm/protocol/gsm_12_21.h>
 
 #include <osmocom/sccp/sccp.h>
@@ -49,7 +49,7 @@
 
 struct gsm_network *bsc_gsmnet = 0;
 static const char *config_file = "openbsc.cfg";
-static const char *rf_ctl = NULL;
+static const char *rf_ctrl = NULL;
 extern const char *openbsc_copyright;
 static int daemonize = 0;
 
@@ -120,7 +120,7 @@
 			log_set_log_level(osmo_stderr_target, atoi(optarg));
 			break;
 		case 'r':
-			rf_ctl = optarg;
+			rf_ctrl = optarg;
 			break;
 		default:
 			/* ignore */
@@ -172,18 +172,57 @@
 }
 
 struct location {
+	struct llist_head list;
+	unsigned long age;
+	int valid;
 	double lat;
 	double lon;
 	double height;
-	unsigned long age;
 };
 
-static struct location myloc;
+static LLIST_HEAD(locations);
+
+void cleanup_locations()
+{
+	struct location *myloc, *tmp;
+	int invalpos = 0, i = 0;
+
+	LOGP(DCTRL, LOGL_DEBUG, "Checking position list.\n");
+	llist_for_each_entry_safe(myloc, tmp, &locations, list) {
+		i++;
+		if (i > 3) {
+			LOGP(DCTRL, LOGL_DEBUG, "Deleting old position.\n");
+			llist_del(&myloc->list);
+			talloc_free(myloc);
+		} else if (!myloc->valid) { /* Only capture the newest of subsequent invalid positions */
+			invalpos++;
+			if (invalpos > 1) {
+				LOGP(DCTRL, LOGL_DEBUG, "Deleting subsequent invalid position.\n");
+				invalpos--;
+				i--;
+				llist_del(&myloc->list);
+				talloc_free(myloc);
+			}
+		} else {
+			invalpos = 0;
+		}
+	}
+	LOGP(DCTRL, LOGL_DEBUG, "Found %i positions.\n", i);
+}
 
 CTRL_CMD_DEFINE(net_loc, "location");
 int get_net_loc(struct ctrl_cmd *cmd, void *data)
 {
-	cmd->reply = talloc_asprintf(cmd, "%lu,%f,%f,%f", myloc.age, myloc.lat, myloc.lon, myloc.height);
+	struct location *myloc;
+
+	if (llist_empty(&locations)) {
+		cmd->reply = talloc_asprintf(cmd, "0,0,0,0,0");
+		return CTRL_CMD_REPLY;
+	} else {
+		myloc = llist_entry(locations.next, struct location, list);
+	}
+
+	cmd->reply = talloc_asprintf(cmd, "%lu,%i,%f,%f,%f", myloc->age, myloc->valid, myloc->lat, myloc->lon, myloc->height);
 	if (!cmd->reply) {
 		cmd->reply = "OOM";
 		return CTRL_CMD_ERROR;
@@ -194,24 +233,38 @@
 
 int set_net_loc(struct ctrl_cmd *cmd, void *data)
 {
-	char *saveptr, *lat, *lon, *height, *age, *tmp;
+	char *saveptr, *lat, *lon, *height, *age, *valid, *tmp;
+	struct location *myloc;
 
 	tmp = talloc_strdup(cmd, cmd->value);
 	if (!tmp)
 		goto oom;
 
+	myloc = talloc_zero(tall_bsc_ctx, struct location);
+	if (!myloc) {
+		talloc_free(tmp);
+		goto oom;
+	}
+	INIT_LLIST_HEAD(&myloc->list);
+
 
 	age = strtok_r(tmp, ",", &saveptr);
+	valid = strtok_r(NULL, ",", &saveptr);
 	lat = strtok_r(NULL, ",", &saveptr);
 	lon = strtok_r(NULL, ",", &saveptr);
 	height = strtok_r(NULL, "\0", &saveptr);
 
-	myloc.age = atol(age);
-	myloc.lat = atof(lat);
-	myloc.lon = atof(lon);
-	myloc.height = atof(height);
+	myloc->age = atol(age);
+	myloc->valid = atoi(valid);
+	myloc->lat = atof(lat);
+	myloc->lon = atof(lon);
+	myloc->height = atof(height);
 	talloc_free(tmp);
 
+	/* Add location to the end of the list */
+	llist_add(&myloc->list, &locations);
+	cleanup_locations();
+
 	return get_net_loc(cmd, data);
 oom:
 	cmd->reply = "OOM";
@@ -220,9 +273,9 @@
 
 int verify_net_loc(struct ctrl_cmd *cmd, const char *value, void *data)
 {
-	char *saveptr, *latstr, *lonstr, *heightstr, *agestr, *tmp;
-	int  ret = 0;
+	char *saveptr, *latstr, *lonstr, *heightstr, *agestr, *validstr, *tmp;
 	unsigned long age;
+	int valid;
 	double lat, lon, height;
 
 	tmp = talloc_strdup(cmd, value);
@@ -230,23 +283,27 @@
 		return 1;
 
 	agestr = strtok_r(tmp, ",", &saveptr);
+	validstr = strtok_r(NULL, ",", &saveptr);
 	latstr = strtok_r(NULL, ",", &saveptr);
 	lonstr = strtok_r(NULL, ",", &saveptr);
 	heightstr = strtok_r(NULL, "\0", &saveptr);
 
-	if ((agestr == 0) || (latstr == 0) || (lonstr == 0) || (heightstr == 0))
-		ret = 1;
+	if ((agestr == NULL) || (validstr == NULL) || (latstr == NULL) ||
+			(lonstr == NULL) || (heightstr == NULL))
+		return 1;
 
 	age = atol(agestr);
+	valid = atoi(validstr);
 	lat = atof(latstr);
 	lon = atof(lonstr);
 	height = atof(heightstr);
 	talloc_free(tmp);
 
-	if ((age == 0) || (lat < -90) || (lat > 90) || (lon < -180) || (lon > 180))
+	if ((age == 0) || (lat < -90) || (lat > 90) || (lon < -180) ||
+			(lon > 180) || (valid < 0) || (valid > 2))
 		return 1;
 
-	return ret;
+	return 0;
 }
 
 CTRL_CMD_DEFINE(trx_rf_lock, "rf_locked");
@@ -371,13 +428,13 @@
 	ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_rf_lock);
 
 	data = bsc_gsmnet->msc_data;
-	if (rf_ctl)
-		bsc_replace_string(data, &data->rf_ctrl_name, rf_ctl);
+	if (rf_ctrl)
+		bsc_replace_string(data, &data->rf_ctrl_name, rf_ctrl);
 
 	if (data->rf_ctrl_name) {
-		data->rf_ctl = osmo_bsc_rf_create(data->rf_ctrl_name,
+		data->rf_ctrl = osmo_bsc_rf_create(data->rf_ctrl_name,
 						  bsc_gsmnet);
-		if (!data->rf_ctl) {
+		if (!data->rf_ctrl) {
 			fprintf(stderr, "Failed to create the RF service.\n");
 			exit(1);
 		}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_rf.c b/openbsc/src/osmo-bsc/osmo_bsc_rf.c
index cd64b52..6e9e027 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_rf.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_rf.c
@@ -243,7 +243,7 @@
 	return 0;
 }
 
-static int rf_ctl_accept(struct osmo_fd *bfd, unsigned int what)
+static int rf_ctrl_accept(struct osmo_fd *bfd, unsigned int what)
 {
 	struct osmo_bsc_rf_conn *conn;
 	struct osmo_bsc_rf *rf = bfd->data;
@@ -338,7 +338,7 @@
 	}
 
 	bfd->when = BSC_FD_READ;
-	bfd->cb = rf_ctl_accept;
+	bfd->cb = rf_ctrl_accept;
 	bfd->data = rf;
 
 	if (osmo_fd_register(bfd) != 0) {
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
index c176908..4f03b52 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
@@ -264,14 +264,14 @@
 static int handle_msc_signal(unsigned int subsys, unsigned int signal,
 			     void *handler_data, void *signal_data)
 {
-	struct osmo_msc_data *data;
+	struct msc_signal_data *msc;
 
 	if (subsys != SS_MSC)
 		return 0;
 
-	data = (struct osmo_msc_data *) signal_data;
+	msc = signal_data;
 	if (signal == S_MSC_LOST)
-		bsc_close_connections(data->msc_con);
+		bsc_close_connections(msc->data->msc_con);
 
 	return 0;
 }
diff --git a/openbsc/src/osmo-bsc_mgcp/mgcp_main.c b/openbsc/src/osmo-bsc_mgcp/mgcp_main.c
index 921fa09..ee1543c 100644
--- a/openbsc/src/osmo-bsc_mgcp/mgcp_main.c
+++ b/openbsc/src/osmo-bsc_mgcp/mgcp_main.c
@@ -2,8 +2,8 @@
 /* The main method to drive it as a standalone process      */
 
 /*
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -40,7 +40,6 @@
 #include <osmocom/core/application.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/talloc.h>
-#include <osmocom/core/process.h>
 #include <osmocom/core/select.h>
 
 #include <osmocom/vty/telnet_interface.h>
@@ -59,6 +58,7 @@
 #warning "Make use of the rtp proxy code"
 
 static struct mgcp_config *cfg;
+static struct mgcp_trunk_config *reset_trunk;
 static int reset_endpoints = 0;
 static int daemonize = 0;
 
@@ -122,9 +122,10 @@
 }
 
 /* simply remember this */
-static int mgcp_rsip_cb(struct mgcp_config *cfg)
+static int mgcp_rsip_cb(struct mgcp_trunk_config *tcfg)
 {
 	reset_endpoints = 1;
+	reset_trunk = tcfg;
 
 	return 0;
 }
@@ -171,12 +172,14 @@
 	}
 
 	if (reset_endpoints) {
-		LOGP(DMGCP, LOGL_NOTICE, "Asked to reset endpoints.\n");
+		LOGP(DMGCP, LOGL_NOTICE,
+		     "Asked to reset endpoints: %d/%d\n",
+		     reset_trunk->trunk_nr, reset_trunk->trunk_type);
 		reset_endpoints = 0;
 
 		/* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */
-		for (i = 1; i < cfg->trunk.number_endpoints; ++i)
-			mgcp_free_endp(&cfg->trunk.endpoints[i]);
+		for (i = 1; i < reset_trunk->number_endpoints; ++i)
+			mgcp_free_endp(&reset_trunk->endpoints[i]);
 	}
 
 	return 0;
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 9ed8e58..445f459 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -47,7 +47,6 @@
 
 #include <osmocom/core/application.h>
 #include <osmocom/core/talloc.h>
-#include <osmocom/core/process.h>
 
 #include <osmocom/gsm/gsm0808.h>
 #include <osmocom/gsm/protocol/gsm_08_08.h>
diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c
index fc67a4d..9693dc4 100644
--- a/openbsc/src/osmo-nitb/bsc_hack.c
+++ b/openbsc/src/osmo-nitb/bsc_hack.c
@@ -32,7 +32,6 @@
 #include <openbsc/db.h>
 #include <osmocom/core/application.h>
 #include <osmocom/core/select.h>
-#include <osmocom/core/process.h>
 #include <openbsc/debug.h>
 #include <openbsc/e1_input.h>
 #include <osmocom/core/talloc.h>
diff --git a/openbsc/src/utils/bs11_config.c b/openbsc/src/utils/bs11_config.c
index 41acd69..ef01072 100644
--- a/openbsc/src/utils/bs11_config.c
+++ b/openbsc/src/utils/bs11_config.c
@@ -35,6 +35,7 @@
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
 #include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
 #include <osmocom/gsm/tlv.h>
 #include <openbsc/debug.h>
 #include <osmocom/core/select.h>
@@ -209,35 +210,31 @@
 	return 0;
 }
 
-static const char *bs11_link_state[] = {
-	[0x00]	= "Down",
-	[0x01]	= "Up",
-	[0x02]	= "Restoring",
+static const struct value_string bs11_linkst_names[] = {
+	{ 0,	"Down" },
+	{ 1,	"Up" },
+	{ 2,	"Restoring" },
+	{ 0,	NULL }
 };
 
 static const char *linkstate_name(uint8_t linkstate)
 {
-	if (linkstate > ARRAY_SIZE(bs11_link_state))
-		return "Unknown";
-
-	return bs11_link_state[linkstate];
+	return get_value_string(bs11_linkst_names, linkstate);
 }
 
-static const char *mbccu_load[] = {
-	[0]	= "No Load",
-	[1]	= "Load BTSCAC",
-	[2]	= "Load BTSDRX",
-	[3]	= "Load BTSBBX",
-	[4]	= "Load BTSARC",
-	[5]	= "Load",
+static const struct value_string mbccu_load_names[] = {
+	{ 0,	"No Load" },
+	{ 1,	"Load BTSCAC" },
+	{ 2,	"Load BTSDRX" },
+	{ 3,	"Load BTSBBX" },
+	{ 4,	"Load BTSARC" },
+	{ 5,	"Load" },
+	{ 0,	NULL }
 };
 
 static const char *mbccu_load_name(uint8_t linkstate)
 {
-	if (linkstate > ARRAY_SIZE(mbccu_load))
-		return "Unknown";
-
-	return mbccu_load[linkstate];
+	return get_value_string(mbccu_load_names, linkstate);
 }
 
 static const char *bts_phase_name(uint8_t phase)
@@ -899,7 +896,8 @@
 	status_timer.cb = status_timer_cb;
 
 	while (1) {
-		osmo_select_main(0);
+		if (osmo_select_main(0) < 0)
+			break;
 	}
 
 	abis_nm_bs11_factory_logon(g_bts, 0);