Move the bulk of RR processing from MSC into BSC

RR Messages like STATUS, GPRS SUSPEND, HANDOVER COMPLETE/FAIL, ...
should be processed on the BSC side of things, not on the MSC side.

This is among other things required in preparation of intra-BSC
hand-over support in osmo-bsc.
diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c
index bb13747..9d301f0 100644
--- a/openbsc/src/libbsc/bsc_api.c
+++ b/openbsc/src/libbsc/bsc_api.c
@@ -438,24 +438,55 @@
 		/* we must have a classmark3 */
 		if (gh->data[cm2_len+1] != 0x20) {
 			DEBUGPC(DRR, "ERR CM3 TAG\n");
-			return -EINVAL;
+			return;
 		}
 		if (cm2_len > 3) {
 			DEBUGPC(DRR, "CM2 too long!\n");
-			return -EINVAL;
+			return;
 		}
 
 		cm3_len = gh->data[cm2_len+2];
 		cm3 = &gh->data[cm2_len+3];
 		if (cm3_len > 14) {
 			DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
-			return -EINVAL;
+			return;
 		}
 		DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
 	}
 	api->classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
 }
 
+/* Chapter 9.1.16 Handover complete */
+static void handle_rr_ho_compl(struct msgb *msg)
+{
+	struct lchan_signal_data sig;
+	struct gsm48_hdr *gh = msgb_l3(msg);
+
+	DEBUGP(DRR, "HANDOVER COMPLETE cause = %s\n",
+		rr_cause_name(gh->data[0]));
+
+	sig.lchan = msg->lchan;
+	sig.mr = NULL;
+	osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
+	/* FIXME: release old channel */
+}
+
+/* Chapter 9.1.17 Handover Failure */
+static void handle_rr_ho_fail(struct msgb *msg)
+{
+	struct lchan_signal_data sig;
+	struct gsm48_hdr *gh = msgb_l3(msg);
+
+	DEBUGP(DRR, "HANDOVER FAILED cause = %s\n",
+		rr_cause_name(gh->data[0]));
+
+	sig.lchan = msg->lchan;
+	sig.mr = NULL;
+	osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
+	/* FIXME: release allocated new channel */
+}
+
+
 static void dispatch_dtap(struct gsm_subscriber_connection *conn,
 			  uint8_t link_id, struct msgb *msg)
 {
@@ -471,12 +502,38 @@
 
 	gh = msgb_l3(msg);
 	pdisc = gh->proto_discr & 0x0f;
+
+	/* the idea is to handle all RR messages here, and only hand
+	 * MM/CC/SMS-CP/LCS up to the MSC.  Some messages like PAGING
+	 * RESPONSE or CM SERVICE REQUEST will not be covered here, as
+	 * they are only possible in the first L3 message of each L2
+	 * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()
+	 * will call api->compl_l3() for it */
 	switch (pdisc) {
 	case GSM48_PDISC_RR:
 		switch (gh->msg_type) {
+		case GSM48_MT_RR_GPRS_SUSP_REQ:
+			DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
+			break;
+		case GSM48_MT_RR_STATUS:
+			DEBUGP(DRR, "RR STATUS (cause: %s)\n",
+				rr_cause_name(gh->data[0]));
+			break;
+		case GSM48_MT_RR_MEAS_REP:
+			/* This shouldn't actually end up here, as RSL treats
+			* L3 Info of 08.58 MEASUREMENT REPORT different by calling
+			* directly into gsm48_parse_meas_rep */
+			LOGP(LOGL_ERROR, DMEAS, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
+			break;
+		case GSM48_MT_RR_HANDO_COMPL:
+			handle_rr_ho_compl(msg);
+			break;
+		case GSM48_MT_RR_HANDO_FAIL:
+			handle_rr_ho_fail(msg);
+			break;
 		case GSM48_MT_RR_CIPH_M_COMPL:
 			if (api->cipher_mode_compl)
-				return api->cipher_mode_compl(conn, msg,
+				api->cipher_mode_compl(conn, msg,
 						conn->lchan->encr.alg_id);
 			break;
 		case GSM48_MT_RR_ASS_COMPL:
@@ -498,21 +555,25 @@
 						  conn->lchan->encr.alg_id,
 						  chan_mode_to_speech(conn->lchan));
 			}
-			return;
 			break;
 		case GSM48_MT_RR_CLSM_CHG:
 			handle_classmark_chg(conn, msg);
-			return;
 			break;
+		default:
+			/* Normally, a MSC should never receive RR
+			 * messages, but we'd rather forward what we
+			 * don't know than drop it... */
+			LOGP(DRR, LOGL_NOTICE, "BSC: Passing unknown 04.08 "
+			     "RR message type 0x%02x to MSC\n", gh->msg_type);
+			if (api->dtap)
+				api->dtap(conn, link_id, msg);
 		}
 		break;
-	case GSM48_PDISC_MM:
+	default:
+		if (api->dtap)
+			api->dtap(conn, link_id, msg);
 		break;
 	}
-
-	/* default case */
-	if (api->dtap)
-		api->dtap(conn, link_id, msg);
 }
 
 /*! \brief RSL has received a DATA INDICATION with L3 from MS */