Implement IuCS (large refactoring and addition)

osmo-nitb becomes osmo-msc
add DIUCS debug log constant
add iucs.[hc]
add msc vty, remove nitb vty
add libiudummy, to avoid linking Iu deps in tests
Use new msc_tx_dtap() instead of gsm0808_submit_dtap()
libmgcp: add mgcpgw client API
bridge calls via mgcpgw

Enable MSC specific CTRL commands, bsc_base_ctrl_cmds_install() still needs to
be split up.

Change-Id: I5b5b6a9678b458affa86800afb1ec726e66eed88
diff --git a/src/libiu/iu.c b/src/libiu/iu.c
index 932b217..5d56a4a 100644
--- a/src/libiu/iu.c
+++ b/src/libiu/iu.c
@@ -80,7 +80,15 @@
 
 void *talloc_iu_ctx;
 
-int asn1_xer_print = 1;
+/* Implement the extern asn_debug from libasn1c to indicate whether to print
+ * asn.1 debug messages (see libasn1c). */
+int asn_debug = 0;
+
+/* Implement the extern asn1_xer_print to indicate whether the ASN.1 binary
+ * code decoded and encoded during Iu communication should be logged to stderr
+ * (see asn.1 generated code in osmo-iuh). */
+int asn1_xer_print = 0;
+
 void *talloc_asn1_ctx;
 
 iu_recv_cb_t global_iu_recv_cb = NULL;
@@ -241,6 +249,25 @@
 	return 0;
 }
 
+int iu_tx_common_id(struct ue_conn_ctx *uectx, const char *imsi)
+{
+	struct msgb *msg;
+	struct osmo_scu_prim *prim;
+
+	LOGP(DRANAP, LOGL_INFO, "Transmitting RANAP CommonID (SUA link %p conn_id %u)\n",
+	     uectx->link, uectx->conn_id);
+
+	msg = ranap_new_msg_common_id(imsi);
+	msg->l2h = msg->data;
+	prim = (struct osmo_scu_prim *) msgb_push(msg, sizeof(*prim));
+	prim->u.data.conn_id = uectx->conn_id;
+	osmo_prim_init(&prim->oph, SCCP_SAP_USER,
+			OSMO_SCU_PRIM_N_DATA,
+			PRIM_OP_REQUEST, msg);
+	osmo_sua_user_link_down(uectx->link, &prim->oph);
+	return 0;
+}
+
 static int iu_grnc_id_parse(struct iu_grnc_id *dst,
 			    struct RANAP_GlobalRNC_ID *src)
 {
@@ -375,20 +402,35 @@
 	return 0;
 }
 
-static int ranap_handle_co_iu_rel_req(struct ue_conn_ctx *ctx, RANAP_Iu_ReleaseRequestIEs_t *ies)
+/* Send Iu Release for the given UE connection.
+ * If cause is NULL, the standard "No remaining RAB" cause is sent, otherwise
+ * the provided cause. */
+int iu_tx_release(struct ue_conn_ctx *ctx, const struct RANAP_Cause *cause)
 {
 	struct msgb *msg;
 	struct osmo_scu_prim *prim;
+	static const struct RANAP_Cause default_cause = {
+		.present = RANAP_Cause_PR_radioNetwork,
+		.choice.radioNetwork = RANAP_CauseRadioNetwork_no_remaining_rab,
+	};
 
-	LOGP(DRANAP, LOGL_INFO, "Received Iu Release Request, Sending Release Command\n");
-	msg = ranap_new_msg_iu_rel_cmd(&ies->cause);
+	if (!cause)
+		cause = &default_cause;
+
+	msg = ranap_new_msg_iu_rel_cmd(cause);
 	msg->l2h = msg->data;
 	prim = (struct osmo_scu_prim *) msgb_push(msg, sizeof(*prim));
 	prim->u.data.conn_id = ctx->conn_id;
 	osmo_prim_init(&prim->oph, SCCP_SAP_USER,
 			OSMO_SCU_PRIM_N_DATA,
 			PRIM_OP_REQUEST, msg);
-	osmo_sua_user_link_down(ctx->link, &prim->oph);
+	return osmo_sua_user_link_down(ctx->link, &prim->oph);
+}
+
+static int ranap_handle_co_iu_rel_req(struct ue_conn_ctx *ctx, RANAP_Iu_ReleaseRequestIEs_t *ies)
+{
+	LOGP(DRANAP, LOGL_INFO, "Received Iu Release Request, Sending Release Command\n");
+	iu_tx_release(ctx, &ies->cause);
 	return 0;
 }
 
@@ -413,6 +455,7 @@
 
 		ranap_free_rab_setupormodifieditemies(&setup_ies);
 	}
+	/* FIXME: handle RAB Ass failure? */
 
 	return rc;
 }
diff --git a/src/libiu/iu_vty.c b/src/libiu/iu_vty.c
index 91eed96..73ad126 100644
--- a/src/libiu/iu_vty.c
+++ b/src/libiu/iu_vty.c
@@ -18,33 +18,91 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
+#include <osmocom/core/logging.h>
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/logging.h>
 
-/* Pointer to the actual asn_debug value as passed from main scopes. */
-static int *g_asn_debug_p = NULL;
+#include <openbsc/iu.h>
+
+static enum nsap_addr_enc *g_rab_assign_addr_enc = NULL;
 
 DEFUN(logging_asn_debug,
       logging_asn_debug_cmd,
       "logging asn1-debug (1|0)",
       LOGGING_STR
+      "Log ASN.1 debug messages to stderr\n"
+      "Log ASN.1 debug messages to stderr\n"
+      "Do not log ASN.1 debug messages to stderr\n")
+{
+	asn_debug = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(logging_asn_xer_print,
+      logging_asn_xer_print_cmd,
+      "logging asn1-xer-print (1|0)",
+      LOGGING_STR
       "Log human readable representations of all ASN.1 messages to stderr\n"
       "Log decoded ASN.1 messages to stderr\n"
       "Do not log decoded ASN.1 messages to stderr\n")
 {
-	if (!g_asn_debug_p) {
-		vty_out(vty, "%%ASN.1 debugging not available%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	*g_asn_debug_p = atoi(argv[0]);
+	asn1_xer_print = atoi(argv[0]);
 	return CMD_SUCCESS;
 }
 
-void iu_vty_init(int *asn_debug_p)
+DEFUN(cfg_iu_rab_assign_addr_enc, cfg_iu_rab_assign_addr_enc_cmd,
+      "iu rab-assign-addr-enc (x213|v4raw)",
+      "Iu interface protocol options\n"
+      "Choose RAB Assignment's Transport Layer Address encoding\n"
+      "ITU-T X.213 compliant address encoding (default)\n"
+      "32bit length raw IPv4 address (for ip.access nano3G)\n")
 {
-	g_asn_debug_p = asn_debug_p;
+	if (!g_rab_assign_addr_enc) {
+		vty_out(vty, "%%RAB Assignment Transport Layer Address"
+			" encoding not available%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (strcmp(argv[0], "v4raw") == 0)
+		*g_rab_assign_addr_enc = NSAP_ADDR_ENC_V4RAW;
+	else
+		*g_rab_assign_addr_enc = NSAP_ADDR_ENC_X213;
+	return CMD_SUCCESS;
+}
+
+int iu_vty_config_write(struct vty *vty, const char *indent)
+{
+	if (!g_rab_assign_addr_enc) {
+		vty_out(vty, "%%RAB Assignment Transport Layer Address"
+			" encoding not available%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	switch (*g_rab_assign_addr_enc) {
+	case NSAP_ADDR_ENC_V4RAW:
+		vty_out(vty, "%siu rab-assign-addr-enc v4raw%s", indent,
+			VTY_NEWLINE);
+		break;
+	case NSAP_ADDR_ENC_X213:
+		/* default value, no need to write anything */
+		break;
+	default:
+		LOGP(0, LOGL_ERROR, "Invalid value for"
+		     " net.iu.rab_assign_addr_enc: %d\n",
+		     *g_rab_assign_addr_enc);
+		return CMD_WARNING;
+	}
+
+	return CMD_SUCCESS;
+}
+
+void iu_vty_init(int iu_parent_node, enum nsap_addr_enc *rab_assign_addr_enc)
+{
+	g_rab_assign_addr_enc = rab_assign_addr_enc;
 
 	install_element(CFG_LOG_NODE, &logging_asn_debug_cmd);
+	install_element(CFG_LOG_NODE, &logging_asn_xer_print_cmd);
+	install_element(iu_parent_node, &cfg_iu_rab_assign_addr_enc_cmd);
 }