implement detection of duplicate packets to catch and avoid forwarding loops

fixes #20
pull/23/head
Richard Fuchs 11 years ago
parent 65812fa2b2
commit c0f8196a25

@ -575,6 +575,7 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
struct call_media *media;
int ret = 0, update = 0, stun_ret = 0, handler_ret = 0, muxed_rtcp = 0, rtcp = 0,
unk = 0;
int i;
struct sockaddr_in6 sin6;
struct msghdr mh;
struct iovec iov;
@ -621,6 +622,32 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
stun_ret = 0;
}
#if RTP_LOOP_PROTECT
for (i = 0; i < RTP_LOOP_PACKETS; i++) {
if (stream->lp_buf[i].len != s->len)
continue;
if (memcmp(stream->lp_buf[i].buf, s->s, MIN(s->len, RTP_LOOP_PROTECT)))
continue;
__C_DBG("packet dupe");
if (stream->lp_count >= RTP_LOOP_MAX_COUNT) {
ilog(LOG_WARNING, "More than %d duplicate packets detected, dropping packet "
"to avoid potential loop", RTP_LOOP_MAX_COUNT);
goto done;
}
stream->lp_count++;
goto loop_ok;
}
/* not a dupe */
stream->lp_count = 0;
stream->lp_buf[stream->lp_idx].len = s->len;
memcpy(stream->lp_buf[stream->lp_idx].buf, s->s, MIN(s->len, RTP_LOOP_PROTECT));
stream->lp_idx = (stream->lp_idx + 1) % RTP_LOOP_PACKETS;
loop_ok:
#endif
mutex_unlock(&stream->in_lock);
in_srtp = stream;

@ -65,6 +65,12 @@ struct call_monologue;
#define RTP_BUFFER_TAIL_ROOM 512
#define RTP_BUFFER_SIZE (MAX_RTP_PACKET_SIZE + RTP_BUFFER_HEAD_ROOM + RTP_BUFFER_TAIL_ROOM)
#ifndef RTP_LOOP_PROTECT
#define RTP_LOOP_PROTECT 16 /* number of bytes */
#define RTP_LOOP_PACKETS 2 /* number of packets */
#define RTP_LOOP_MAX_COUNT 30 /* number of consecutively detected dupes to trigger protection */
#endif
#ifdef __DEBUG
#define __C_DBG(x...) ilog(LOG_DEBUG, x)
#else
@ -215,6 +221,11 @@ struct endpoint_map {
int wildcard:1;
};
struct loop_protector {
unsigned int len;
unsigned char buf[RTP_LOOP_PROTECT];
};
struct packet_stream {
mutex_t in_lock,
out_lock;
@ -238,6 +249,13 @@ struct packet_stream {
struct stats kernel_stats; /* LOCK: in_lock */
time_t last_packet; /* LOCK: in_lock */
#if RTP_LOOP_PROTECT
/* LOCK: in_lock: */
unsigned int lp_idx;
struct loop_protector lp_buf[RTP_LOOP_PACKETS];
unsigned int lp_count;
#endif
X509 *dtls_cert; /* LOCK: in_lock */
/* in_lock must be held for SETTING these: */

Loading…
Cancel
Save