nat: Make mode-set patching optional
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 9d29d26..19144e3 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -285,6 +285,7 @@
 	uint8_t mgcp_msg[4096];
 	int mgcp_length;
 	int mgcp_ipa;
+	int sdp_ensure_amr_mode_set;
 
 	/* msc things */
 	struct llist_head dests;
@@ -421,7 +422,7 @@
 
 struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
 struct msgb *bsc_mgcp_rewrite(char *input, int length, int endp, const char *ip,
-			      int port, int osmux, int *payload_type);
+			      int port, int osmux, int *payload_type, int mode_set);
 void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
 
 void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc);
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
index 9759303..5a024db 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
@@ -552,7 +552,8 @@
 	bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
 				   sccp->bsc_endp, nat->mgcp_cfg->source_addr,
 				   mgcp_endp->bts_end.local_port, osmux_cid,
-				   &mgcp_endp->net_end.codec.payload_type);
+				   &mgcp_endp->net_end.codec.payload_type,
+				   nat->sdp_ensure_amr_mode_set);
 	if (!bsc_msg) {
 		LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n");
 		return MGCP_POLICY_CONT;
@@ -746,7 +747,8 @@
 	output = bsc_mgcp_rewrite((char * ) msg->l2h, msgb_l2len(msg), -1,
 				  bsc->nat->mgcp_cfg->source_addr,
 				  endp->net_end.local_port, -1,
-				  &endp->bts_end.codec.payload_type);
+				  &endp->bts_end.codec.payload_type,
+				  bsc->nat->sdp_ensure_amr_mode_set);
 	if (!output) {
 		LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
 		return;
@@ -813,7 +815,7 @@
 /* we need to replace some strings... */
 struct msgb *bsc_mgcp_rewrite(char *input, int length, int endpoint,
 			      const char *ip, int port, int osmux_cid,
-			      int *payload_type)
+			      int *payload_type, int ensure_mode_set)
 {
 	static const char crcx_str[] = "CRCX ";
 	static const char dlcx_str[] = "DLCX ";
@@ -898,7 +900,7 @@
 	 * the above code made sure that we have 128 bytes lefts. So we can
 	 * safely append another line.
 	 */
-	if (!found_fmtp && payload != -1) {
+	if (ensure_mode_set && !found_fmtp && payload != -1) {
 		snprintf(buf, sizeof(buf) - 1, "a=fmtp:%d mode-set=2%s",
 			payload, cr ? "\r\n" : "\n");
 		buf[sizeof(buf) - 1] = '\0';
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 93a9145..5c3b696 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -1526,6 +1526,9 @@
 		return -5;
 	}
 
+	/* We need to add mode-set for amr codecs */
+	nat->sdp_ensure_amr_mode_set = 1;
+
 	vty_info.copyright = openbsc_copyright;
 	vty_init(&vty_info);
 	logging_vty_add_cmds(&log_info);
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index 2b7db2e..9e66cdc 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -156,6 +156,8 @@
 		write_pgroup_lst(vty, pgroup);
 	if (_nat->mgcp_ipa)
 		vty_out(vty, " use-msc-ipa-for-mgcp%s", VTY_NEWLINE);
+	vty_out(vty, " %ssdp-ensure-amr-mode-set%s",
+		_nat->sdp_ensure_amr_mode_set ? "" : "no ", VTY_NEWLINE);
 
 	return CMD_SUCCESS;
 }
@@ -773,6 +775,24 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_nat_sdp_amr_mode_set,
+      cfg_nat_sdp_amr_mode_set_cmd,
+      "sdp-ensure-amr-mode-set",
+      "Ensure that SDP records include a mode-set\n")
+{
+	_nat->sdp_ensure_amr_mode_set = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_no_sdp_amr_mode_set,
+      cfg_nat_no_sdp_amr_mode_set_cmd,
+      "no sdp-ensure-amr-mode-set",
+      NO_STR "Ensure that SDP records include a mode-set\n")
+{
+	_nat->sdp_ensure_amr_mode_set = 0;
+	return CMD_SUCCESS;
+}
+
 /* per BSC configuration */
 DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR",
       "BSC configuration\n" "Identifier of the BSC\n")
@@ -1274,6 +1294,9 @@
 	install_element(NAT_NODE, &cfg_nat_prefix_trie_cmd);
 	install_element(NAT_NODE, &cfg_nat_no_prefix_trie_cmd);
 
+	install_element(NAT_NODE, &cfg_nat_sdp_amr_mode_set_cmd);
+	install_element(NAT_NODE, &cfg_nat_no_sdp_amr_mode_set_cmd);
+
 	install_element(NAT_NODE, &cfg_nat_pgroup_cmd);
 	install_element(NAT_NODE, &cfg_nat_no_pgroup_cmd);
 	install_node(&pgroup_node, config_write_pgroup);
diff --git a/openbsc/tests/bsc-nat/bsc_data.c b/openbsc/tests/bsc-nat/bsc_data.c
index d1f8ebc..3f1f527 100644
--- a/openbsc/tests/bsc-nat/bsc_data.c
+++ b/openbsc/tests/bsc-nat/bsc_data.c
@@ -171,6 +171,7 @@
 /* different line ending */
 static const char mdcx_resp2[] = "200 33330829\n\nv=0\nc=IN IP4 172.16.18.2\nm=audio 4002 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
 static const char mdcx_resp_patched2[] = "200 33330829\n\nv=0\nc=IN IP4 10.0.0.23\nm=audio 5555 RTP/AVP 98\na=rtpmap:98 AMR/8000\na=fmtp:98 mode-set=2\n";
+static const char mdcx_resp_patched2_noamr[] = "200 33330829\n\nv=0\nc=IN IP4 10.0.0.23\nm=audio 5555 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
 
 struct mgcp_patch_test {
 	const char *orig;
@@ -178,6 +179,7 @@
 	const char *ip;
 	const int port;
 	const int payload_type;
+	const int ensure_mode_set;
 };
 
 static const struct mgcp_patch_test mgcp_messages[] = {
@@ -186,6 +188,7 @@
 		.patch = crcx_patched,
 		.ip = "0.0.0.0",
 		.port = 2323,
+		.ensure_mode_set = 1,
 	},
 	{
 		.orig = crcx_resp,
@@ -193,6 +196,7 @@
 		.ip = "10.0.0.1",
 		.port = 999,
 		.payload_type = 98,
+		.ensure_mode_set = 1,
 	},
 	{
 		.orig = mdcx,
@@ -200,6 +204,7 @@
 		.ip = "10.0.0.23",
 		.port = 6666,
 		.payload_type = 126,
+		.ensure_mode_set = 1,
 	},
 	{
 		.orig = mdcx_resp,
@@ -207,6 +212,7 @@
 		.ip = "10.0.0.23",
 		.port = 5555,
 		.payload_type = 98,
+		.ensure_mode_set = 1,
 	},
 	{
 		.orig = mdcx_resp2,
@@ -214,6 +220,15 @@
 		.ip = "10.0.0.23",
 		.port = 5555,
 		.payload_type = 98,
+		.ensure_mode_set = 1,
+	},
+	{
+		.orig = mdcx_resp2,
+		.patch = mdcx_resp_patched2_noamr,
+		.ip = "10.0.0.23",
+		.port = 5555,
+		.payload_type = 98,
+		.ensure_mode_set = 0,
 	},
 };
 
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 245b081..5b01cc3 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -625,12 +625,13 @@
 		const char *ip = mgcp_messages[i].ip;
 		const int port = mgcp_messages[i].port;
 		const int expected_payload_type = mgcp_messages[i].payload_type;
+		const int ensure_mode_set = mgcp_messages[i].ensure_mode_set;
 		int payload_type = -1;
 
 		char *input = strdup(orig);
 
 		output = bsc_mgcp_rewrite(input, strlen(input), 0x1e,
-					  ip, port, -1, &payload_type);
+					  ip, port, -1, &payload_type, ensure_mode_set);
 
 		if (payload_type != -1) {
 			fprintf(stderr, "Found media payload type %d in SDP data\n",
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index fb4ca7d..3581b67 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -588,6 +588,23 @@
         res = self.vty.command("number-rewrite rewrite.cfg")
         res = self.vty.command("no number-rewrite")
 
+    def testEnsureNoEnsureModeSet(self):
+        self.vty.enable()
+        res = self.vty.command("configure terminal")
+        res = self.vty.command("nat")
+
+        # Ensure the default
+        res = self.vty.command("show running-config")
+        self.assert_(res.find('\n sdp-ensure-amr-mode-set') > 0)
+
+        self.vty.command("sdp-ensure-amr-mode-set")
+        res = self.vty.command("show running-config")
+        self.assert_(res.find('\n sdp-ensure-amr-mode-set') > 0)
+
+        self.vty.command("no sdp-ensure-amr-mode-set")
+        res = self.vty.command("show running-config")
+        self.assert_(res.find('\n no sdp-ensure-amr-mode-set') > 0)
+
     def testRewritePostNoRewrite(self):
         self.vty.enable()
         self.vty.command("configure terminal")