mncc_sock: Add new 'mncc handler' function

This adds mncc_sock_from_cc() as a handler function for CC messages
to be passed to the MNCC interface.  If there is no MNCC socket
registered, we immediately release any CC related messages.

Together with flushing all established CC transaction at MNCC socket
close time, this ensures that all resources are released and no
new resources can be established until the MNCC applicaiton has
re-attached.
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index 75551c5..2fc8e0b 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -156,8 +156,13 @@
 };
 
 char *get_mncc_name(int value);
-int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
 void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
 void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
 
+/* input from CC code into mncc_builtin */
+int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
+
+/* input from CC code into mncc_sock */
+void mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
+
 #endif
diff --git a/openbsc/src/mncc_sock.c b/openbsc/src/mncc_sock.c
index 7e0a208..acd1666 100644
--- a/openbsc/src/mncc_sock.c
+++ b/openbsc/src/mncc_sock.c
@@ -32,6 +32,7 @@
 
 #include <osmocore/talloc.h>
 #include <osmocore/select.h>
+#include <osmocore/protocol/gsm_04_08.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/mncc.h>
@@ -46,6 +47,38 @@
 /* FIXME: avoid this */
 static struct mncc_sock_state *g_state;
 
+/* input from CC code into mncc_sock */
+void mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg)
+{
+	struct gsm_mncc *mncc_in = msgb_data(msg);
+	int msg_type = mncc_in->msg_type;
+
+	/* Check if we currently have a MNCC handler connected */
+	if (g_state->conn_bfd.fd < 0) {
+		LOGP(DMNCC, LOGL_ERROR, "mncc_sock receives %s for external CC app "
+			"but socket is gone\n", get_mncc_name(msg_type));
+		if (msg_type != GSM_TCHF_FRAME &&
+		    msg_type != GSM_TCHF_FRAME_EFR) {
+			/* release the request */
+			struct gsm_mncc mncc_out;
+			memset(&mncc_out, 0, sizeof(mncc_out));
+			mncc_out.callref = mncc_in->callref;
+			mncc_set_cause(&mncc_out, GSM48_CAUSE_LOC_PRN_S_LU,
+					GSM48_CC_CAUSE_TEMP_FAILURE);
+			mncc_tx_to_cc(net, MNCC_REL_REQ, &mncc_out);
+		}
+		/* free the original message */
+		msgb_free(msg);
+		return;
+	}
+
+	/* FIXME: check for some maximum queue depth? */
+
+	/* Actually enqueue the message and mark socket write need */
+	msgb_enqueue(&net->upqueue, msg);
+	g_state->conn_bfd.when |= BSC_FD_WRITE;
+}
+
 void mncc_sock_write_pending(void)
 {
 	g_state->conn_bfd.when |= BSC_FD_WRITE;