[4/9] Add support for AMR frames to MNCC/RTP interface
diff mbox

Message ID 536605C1.8080206@eversberg.eu
State Superseded
Headers show

Commit Message

Andreas Eversberg May 4, 2014, 9:17 a.m. UTC
>>> i had that patch done already. (see attachment)
>> what was the message id?  I didn't see it.
> Could you please answer this one?
hi holger,

sorry, i did not express myself well enough. i meant that i already 
wrote the patch, but did not send it to the mailing list.
>> This lacks input validation. The code needs to check that the data
>> we read is within the bounds of the msgb and the data we write is within
>> the bounds too.
i added a check that limits the GSM frames to 33 octets (full speech). 
(AMR requires only 31 octets + 1 octet length indicator.) an MNCC 
message has much larger msgb allocation when received. see attachment.

best regards

andreas

Patch
diff mbox

From 9175347f5a357317feba67e82b4ff3bc3aca5baf Mon Sep 17 00:00:00 2001
From: Andreas Eversberg <jolly@eversberg.eu>
Date: Thu, 8 Mar 2012 14:39:19 +0100
Subject: [PATCH] Add support for AMR frames to MNCC/RTP interface

AMR rate is currently fixed to 5.9k.
---
 openbsc/src/libmsc/gsm_04_08.c  |  1 +
 openbsc/src/libtrau/rtp_proxy.c | 53 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index df93433..a0650ab 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -2953,6 +2953,7 @@  int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
 	case GSM_TCHF_FRAME:
 	case GSM_TCHF_FRAME_EFR:
 	case GSM_TCHH_FRAME:
+	case GSM_TCH_FRAME_AMR:
 		/* Find callref */
 		trans = trans_find_by_callref(net, data->callref);
 		if (!trans) {
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 143bfa0..95729ef 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -192,21 +192,41 @@  static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
 			return -EINVAL;
 		}
 		break;
+	case RTP_PT_AMR:
+		break;
 	default:
 		DEBUGPC(DLMUX, "received RTP frame with unknown payload "
 			"type %d\n", rtph->payload_type);
 		return -EINVAL;
 	}
 
-	new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + payload_len,
-				"GSM-DATA");
+	if (payload_len > 33) {
+		DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
+			payload_len);
+		return -EINVAL;
+	}
+
+	if (rtph->payload_type == RTP_PT_AMR) {
+		new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + 1
+				     + payload_len, "GSM-DATA (AMR)");
+	} else {
+		new_msg = msgb_alloc(sizeof(struct gsm_data_frame)
+				     + payload_len, "GSM-DATA");
+	}
 	if (!new_msg)
 		return -ENOMEM;
 	frame = (struct gsm_data_frame *)(new_msg->data);
 	frame->msg_type = msg_type;
 	frame->callref = callref;
-	memcpy(frame->data, payload, payload_len);
-	msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len);
+	if (rtph->payload_type == RTP_PT_AMR) {
+		frame->data[0] = payload_len;
+		msgb_put(new_msg, sizeof(struct gsm_data_frame) + 1
+					 + payload_len);
+		memcpy(frame->data + 1, payload, payload_len);
+	} else {
+		msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len);
+		memcpy(frame->data, payload, payload_len);
+	}
 
 	*data = new_msg;
 	return 0;
@@ -264,6 +284,11 @@  int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
 		payload_len = RTP_LEN_GSM_HALF;
 		duration = RTP_GSM_DURATION;
 		break;
+	case GSM_TCH_FRAME_AMR:
+		payload_type = RTP_PT_AMR;
+		payload_len = frame->data[0];
+		duration = RTP_GSM_DURATION;
+		break;
 	default:
 		DEBUGPC(DLMUX, "unsupported message type %d\n",
 			frame->msg_type);
@@ -291,7 +316,18 @@  int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
 		}
 	}
 
-	msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM-FULL");
+	if (payload_len > 33) {
+		DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
+			payload_len);
+		return -EINVAL;
+	}
+
+	if (frame->msg_type == GSM_TCH_FRAME_AMR)
+		msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len,
+			"RTP-GSM (AMR)");
+	else
+		msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len,
+			"RTP-GSM");
 	if (!msg)
 		return -ENOMEM;
 	rtph = (struct rtp_hdr *)msg->data;
@@ -305,7 +341,12 @@  int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
 	rtph->timestamp = htonl(rs->transmit.timestamp);
 	rs->transmit.timestamp += duration;
 	rtph->ssrc = htonl(rs->transmit.ssrc);
-	memcpy(msg->data + sizeof(struct rtp_hdr), frame->data, payload_len);
+	if (frame->msg_type == GSM_TCH_FRAME_AMR)
+		memcpy(msg->data + sizeof(struct rtp_hdr), frame->data + 1,
+			payload_len);
+	else
+		memcpy(msg->data + sizeof(struct rtp_hdr), frame->data,
+			payload_len);
 	msgb_put(msg, sizeof(struct rtp_hdr) + payload_len);
 	msgb_enqueue(&rss->tx_queue, msg);
 	rss->bfd.when |= BSC_FD_WRITE;
-- 
1.8.1.5