diff --git a/daemon/Makefile b/daemon/Makefile index c59480a33..cca427178 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -28,7 +28,7 @@ LDFLAGS+= `dpkg-buildflags --get LDFLAGS` endif SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \ - bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c + bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c stun.c OBJS= $(SRCS:.c=.o) diff --git a/daemon/call.c b/daemon/call.c index a248f3a3c..bbfecb7b0 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -25,6 +25,7 @@ #include "bencode.h" #include "sdp.h" #include "str.h" +#include "stun.h" @@ -233,6 +234,11 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_ m = c->callmaster; smart_ntop_port(addr, fsin, sizeof(addr)); + if (r->stun && is_stun(b, l)) { + if (!stun(b, l)) + return 0; + } + if (p->fd.fd == -1) { mylog(LOG_WARNING, LOG_PREFIX_C "RTP packet to port %u discarded from %s", LOG_PARAMS_C(c), r->fd.localport, addr); diff --git a/daemon/call.h b/daemon/call.h index 2e5723aee..80fb2087e 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -78,6 +78,7 @@ struct streamrelay { struct stats stats; struct stats kstats; time_t last; + int stun:1; }; struct relays_cache { struct udp_fd relays_A[16]; diff --git a/daemon/sdp.c b/daemon/sdp.c index 1d845a16d..e754f2304 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -866,6 +866,9 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, chopper_append_c(chop, "\r\na=ice-pwd:"); chopper_append_str(chop, &call->ice_pwd); chopper_append_c(chop, "\r\n"); + + rtp->stun = 1; + rtcp->stun = 1; } for (k = session->media_streams.head; k; k = k->next) { diff --git a/daemon/stun.c b/daemon/stun.c new file mode 100644 index 000000000..4af0c9e7c --- /dev/null +++ b/daemon/stun.c @@ -0,0 +1,24 @@ +#include "stun.h" +#include + +struct stun { + u_int16_t msg_type; + u_int16_t msg_len; + u_int32_t cookie; + unsigned char transaction[12]; +} __attribute__ ((packed)); + + +int stun(const char *buf, int len) { + const struct stun *s = (const void *) buf; + int msglen, method, class; + + msglen = ntohs(s->msg_len); + class = method = ntohl(s->msg_type); + class = ((class & 0x10) >> 4) | ((class & 0x100) >> 7); + method = (method & 0xf) | ((method & 0xe0) >> 1) | ((method & 0x3e00) >> 2); + if (method != 0x1) /* binding */ + return -1; + + return 0; +} diff --git a/daemon/stun.h b/daemon/stun.h new file mode 100644 index 000000000..3f97ff677 --- /dev/null +++ b/daemon/stun.h @@ -0,0 +1,30 @@ +#ifndef _STUN_H_ +#define _STUN_H_ + + +#include +#include + + +static inline int is_stun(const char *bx, int len) { + const unsigned char *b = (const void *) bx; + const u_int32_t *u; + + if (len < 20) + return 0; + if ((b[0] & 0xb0) != 0x00) + return 0; + if ((b[3] & 0x3) != 0x0) + return 0; + u = (const void *) &b[4]; + if (*u != htonl(0x2112A442)) + return 0; + + return 1; +} + + +int stun(const char *buf, int len); + + +#endif