aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2013-05-24 11:56:07 +0200
committerPablo Neira Ayuso <pablo@gnumonks.org>2013-05-24 12:16:49 +0200
commit70214a15d1d575802d821c3555f61c3797a0a89b (patch)
treeb5cf3b05f2b25c93c6694b8044046c4c48f40df4 /src
parent9d6d126c230f480510622dbb1a0f13cdef640146 (diff)
osmux: further sanity checkings for AMR FT
According to RFC3267, AMR FT upper 9 should be discarded. This patch adds extra validation to make sure that input RTP traffic encapsulating AMR payload and OSMUX amr_ft field are OK with regards to that restriction.
Diffstat (limited to 'src')
-rw-r--r--src/amr.c19
-rw-r--r--src/osmux.c30
2 files changed, 44 insertions, 5 deletions
diff --git a/src/amr.c b/src/amr.c
index a6f6a32..55b9300 100644
--- a/src/amr.c
+++ b/src/amr.c
@@ -41,3 +41,22 @@ size_t osmo_amr_bytes(uint8_t amr_ft)
{
return amr_ft_to_bytes[amr_ft];
}
+
+int osmo_amr_ft_valid(uint8_t amr_ft)
+{
+ /*
+ * Extracted from RFC3267:
+ *
+ * "... with a FT value in the range 9-14 for AMR ... the whole packet
+ * SHOULD be discarded."
+ *
+ * "... packets containing only NO_DATA frames (FT=15) SHOULD NOT be
+ * transmitted."
+ *
+ * So, let's discard frames with a AMR FT >= 9.
+ */
+ if (amr_ft >= 9)
+ return 0;
+
+ return 1;
+}
diff --git a/src/osmux.c b/src/osmux.c
index 9438d42..a844372 100644
--- a/src/osmux.c
+++ b/src/osmux.c
@@ -59,6 +59,13 @@ struct osmux_hdr *osmux_xfrm_output_pull(struct msgb *msg)
size_t len;
osmuxh = (struct osmux_hdr *)msg->data;
+
+ if (!osmo_amr_ft_valid(osmuxh->amr_ft)) {
+ LOGP(DLMIB, LOGL_ERROR, "Discarding bad AMR FT %d\n",
+ osmuxh->amr_ft);
+ return NULL;
+ }
+
len = osmo_amr_bytes(osmuxh->amr_ft) * (osmuxh->ctr+1) +
sizeof(struct osmux_hdr);
@@ -311,6 +318,9 @@ static int osmux_rtp_amr_payload_len(struct msgb *msg, struct rtp_hdr *rtph)
if (amrh == NULL)
return -1;
+ if (!osmo_amr_ft_valid(amrh->ft))
+ return -1;
+
return amr_len - sizeof(struct amr_hdr);
}
@@ -367,7 +377,7 @@ osmux_batch_add(struct osmux_batch *batch, struct msgb *msg, int ccid)
{
struct rtp_hdr *rtph;
struct batch_list_node *node;
- int found = 0, bytes = 0;
+ int found = 0, bytes = 0, amr_payload_len;
llist_for_each_entry(node, &batch->node_list, head) {
if (node->ccid == ccid) {
@@ -380,8 +390,12 @@ osmux_batch_add(struct osmux_batch *batch, struct msgb *msg, int ccid)
if (rtph == NULL)
return 0;
+ amr_payload_len = osmux_rtp_amr_payload_len(msg, rtph);
+ if (amr_payload_len < 0)
+ return 0;
+
/* First check if there is room for this message in the batch */
- bytes += osmux_rtp_amr_payload_len(msg, rtph);
+ bytes += amr_payload_len;
if (!found)
bytes += sizeof(struct osmux_hdr);
@@ -443,7 +457,7 @@ osmux_batch_add(struct osmux_batch *batch, struct msgb *msg, int ccid)
*/
int osmux_xfrm_input(struct osmux_in_handle *h, struct msgb *msg, int ccid)
{
- int ret;
+ int ret, first_rtp_msg;
struct rtp_hdr *rtph;
struct osmux_batch *batch = (struct osmux_batch *)h->internal_data;
@@ -463,14 +477,20 @@ int osmux_xfrm_input(struct osmux_in_handle *h, struct msgb *msg, int ccid)
/* This is the first message in the batch, start the
* batch timer to deliver it.
*/
- if (llist_empty(&batch->node_list)) {
+ first_rtp_msg = llist_empty(&batch->node_list) ? 1 : 0;
+
+ /* Add this RTP to the OSMUX batch */
+ ret = osmux_batch_add(batch, msg, ccid);
+ if (ret < 0)
+ return 0;
+
+ if (first_rtp_msg) {
LOGP(DLMIB, LOGL_DEBUG,
"osmux start timer batch\n");
osmo_timer_schedule(&batch->timer, 0,
h->batch_factor * DELTA_RTP_MSG);
}
- ret = osmux_batch_add(batch, msg, ccid);
break;
}
return ret;