diff --git a/daemon/call.c b/daemon/call.c index 045e43f3f..ed07dfdba 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -332,6 +332,7 @@ void kernelize(struct packet_stream *stream) { mpt.dst_addr.port = sink->endpoint.port; mpt.rtcp_mux = MEDIA_ISSET(stream->media, RTCP_MUX); mpt.dtls = MEDIA_ISSET(stream->media, DTLS); + mpt.stun = PS_ISSET(stream, STUN); if (IN6_IS_ADDR_V4MAPPED(&sink->endpoint.ip46)) { mpt.src_addr.family = AF_INET; diff --git a/kernel-module/xt_MEDIAPROXY.c b/kernel-module/xt_MEDIAPROXY.c index 35e3952d6..2582788d5 100644 --- a/kernel-module/xt_MEDIAPROXY.c +++ b/kernel-module/xt_MEDIAPROXY.c @@ -218,6 +218,7 @@ struct rtp_parsed { unsigned int header_len; unsigned char *payload; unsigned int payload_len; + int ok; }; @@ -1807,12 +1808,10 @@ drop: /* XXX shared code */ -static int parse_rtp(struct rtp_parsed *rtp, struct sk_buff *skb) { +static void parse_rtp(struct rtp_parsed *rtp, struct sk_buff *skb) { struct rtp_extension *ext; int ext_len; - memset(rtp, 0, sizeof(*rtp)); - if (skb->len < sizeof(*rtp->header)) goto error; rtp->header = (void *) skb->data; @@ -1834,18 +1833,18 @@ static int parse_rtp(struct rtp_parsed *rtp, struct sk_buff *skb) { ext = (void *) rtp->payload; ext_len = 4 + ntohs(ext->length) * 4; if (rtp->payload_len < ext_len) - return -1; + goto error; rtp->payload += ext_len; rtp->payload_len -= ext_len; } DBG("rtp header parsed, payload length is %u\n", rtp->payload_len); - return 0; + rtp->ok = 1; + return; error: - memset(rtp, 0, sizeof(*rtp)); - return -1; + rtp->ok = 0; } /* XXX shared code */ @@ -2115,6 +2114,16 @@ static unsigned int mediaproxy46(struct sk_buff *skb, struct mediaproxy_table *t DBG("udp payload = %u\n", datalen); skb_trim(skb, datalen); + g = get_target(t, ntohs(uh->dest)); + if (!g) + goto skip2; + + DBG("target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr)); + DBG("target decrypt hmac and cipher are %s and %s", g->decrypt.hmac->name, + g->decrypt.cipher->name); + + if (!g->target.stun) + goto not_stun; if (datalen < 28) goto not_stun; if ((datalen & 0x3)) @@ -2129,19 +2138,15 @@ static unsigned int mediaproxy46(struct sk_buff *skb, struct mediaproxy_table *t goto not_stun; /* probably stun, pass to application */ - goto skip2; + goto skip1; not_stun: - g = get_target(t, ntohs(uh->dest)); - if (!g) - goto skip2; - - DBG("target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr)); - DBG("target decrypt hmac and cipher are %s and %s", g->decrypt.hmac->name, - g->decrypt.cipher->name); - - if (parse_rtp(&rtp, skb)) - goto skip1; + parse_rtp(&rtp, skb); + if (rtp.ok) { + if (g->target.rtp_only) + goto skip1; + goto not_rtp; + } if (g->target.rtcp_mux && is_muxed_rtcp(&rtp)) goto skip1; if (g->target.dtls && is_dtls(&rtp)) @@ -2161,6 +2166,7 @@ not_stun: rtp.payload[12], rtp.payload[13], rtp.payload[14], rtp.payload[15], rtp.payload[16], rtp.payload[17], rtp.payload[18], rtp.payload[19]); +not_rtp: if (g->target.mirror_addr.family) { DBG("sending mirror packet to dst "MIPF"\n", MIPP(g->target.mirror_addr)); skb2 = skb_copy(skb, GFP_ATOMIC); @@ -2172,9 +2178,11 @@ not_stun: } } - srtp_encrypt(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx); - skb_put(skb, g->target.encrypt.mki_len + g->target.encrypt.auth_tag_len); - srtp_authenticate(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx); + if (rtp.ok) { + srtp_encrypt(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx); + skb_put(skb, g->target.encrypt.mki_len + g->target.encrypt.auth_tag_len); + srtp_authenticate(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx); + } err = send_proxy_packet(skb, &g->target.src_addr, &g->target.dst_addr, g->target.tos); diff --git a/kernel-module/xt_MEDIAPROXY.h b/kernel-module/xt_MEDIAPROXY.h index bd9d0f402..5e7b56412 100644 --- a/kernel-module/xt_MEDIAPROXY.h +++ b/kernel-module/xt_MEDIAPROXY.h @@ -66,7 +66,9 @@ struct mediaproxy_target_info { unsigned char tos; int rtcp_mux:1, - dtls:1; + dtls:1, + stun:1, + rtp_only:1; }; struct mediaproxy_message {