From 9e8dc05960f6ac75cafba4b4dce7caaba36736bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 12 Jul 2016 22:35:57 +0200 Subject: [PATCH] rtp: properly dissect RTP and RTCP packets Do not rely on the incoming port number being even or odd in order to identify data as RTP or RTCP respectively. --- src/rtp.c | 47 ++++++++++++++++++++++++++++++++++++----------- src/rtp.h | 22 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/rtp.c b/src/rtp.c index 6424522..cd24cdb 100644 --- a/src/rtp.c +++ b/src/rtp.c @@ -176,16 +176,7 @@ rtp_check_packet(packet_t *packet) src = packet->src; dst = packet->dst; - // Check if we have at least RTP type - if ((int32_t) size < 2) - return NULL; - - // Check RTP version - if (RTP_VERSION(*payload) != RTP_VERSION_RFC1889) - return NULL; - - // RTP: even, RTCP: odd - if (((packet->dst.port % 2) == 0)) { + if (data_is_rtp(payload, size) == 0) { // Get RTP payload type format = RTP_PAYLOAD_TYPE(*(payload + 1)); @@ -221,7 +212,7 @@ rtp_check_packet(packet_t *packet) // Add packet to stream stream_add_packet(stream, packet); - } else { + } else if (data_is_rtcp(payload, size) == 0) { // Find the matching stream if ((stream = rtp_find_stream(src, dst))) { @@ -294,6 +285,8 @@ rtp_check_packet(packet_t *packet) stream_complete(stream, src); stream_add_packet(stream, packet); } + } else { + return NULL; } return stream; @@ -428,3 +421,35 @@ stream_is_complete(rtp_stream_t *stream) { return (stream->pktcnt != 0); } + +int +data_is_rtp(u_char *data, uint32_t len) +{ + u_char pt = RTP_PAYLOAD_TYPE(*(data + 1)); + + if ((len >= RTP_HDR_LENGTH) && + (RTP_VERSION(*data) == RTP_VERSION_RFC1889) && + (data[0] > 127 && data[0] < 192) && + (pt <= 64 || pt >= 96)) { + return 0; + } + + // Not a RTP packet + return 1; +} + +int +data_is_rtcp(u_char *data, uint32_t len) +{ + struct rtcp_hdr_generic *hdr = (struct rtcp_hdr_generic*) data; + + if ((len >= RTCP_HDR_LENGTH) && + (RTP_VERSION(*data) == RTP_VERSION_RFC1889) && + (data[0] > 127 && data[0] < 192) && + (hdr->type >= 192 && hdr->type <= 223)) { + return 0; + } + + // Not a RTCP packet + return 1; +} diff --git a/src/rtp.h b/src/rtp.h index 1aae154..c98e8b4 100644 --- a/src/rtp.h +++ b/src/rtp.h @@ -44,6 +44,12 @@ // Handled RTP versions #define RTP_VERSION_RFC1889 2 +// RTP header length +#define RTP_HDR_LENGTH 12 + +// RTCP common header length +#define RTCP_HDR_LENGTH 4 + // RTCP header types //! http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml enum rtcp_header_types @@ -312,4 +318,20 @@ stream_is_older(rtp_stream_t *one, rtp_stream_t *two); int stream_is_complete(rtp_stream_t *stream); +/** + * @brief Check if the data is a RTP packet + * RFC 5761 Section 4. Distinguishable RTP and RTCP Packets + * RFC 5764 Section 5.1.2. Reception (packet demultiplexing) + */ +int +data_is_rtp(u_char *data, uint32_t len); + +/** + * @brief Check if the data is a RTCP packet + * RFC 5761 Section 4. Distinguishable RTP and RTCP Packets + * RFC 5764 Section 5.1.2. Reception (packet demultiplexing) + */ +int +data_is_rtcp(u_char *data, uint32_t len); + #endif /* __SNGREP_RTP_H */