Skip to content

Commit 3a57fac

Browse files
committed
TT#146201 support forwarding RTCP FB packets directly
Change-Id: I604c750a1d88f07bd5a4a8551bba30b864c4d150
1 parent c03362c commit 3a57fac

File tree

5 files changed

+323
-31
lines changed

5 files changed

+323
-31
lines changed

daemon/media_socket.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,11 +1484,18 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out
14841484

14851485
ZERO(stream->kernel_stats_in);
14861486

1487-
if (proto_is_rtp(media->protocol) && sinks && sinks->length) {
1487+
if (proto_is_rtp(media->protocol)) {
1488+
reti->rtp = 1;
1489+
if (!media->monologue->transcoding) {
1490+
if (media->protocol->avpf)
1491+
reti->rtcp_fb_fw = 1;
1492+
}
1493+
}
1494+
1495+
if (reti->rtp && sinks && sinks->length) {
14881496
GList *l;
14891497
struct rtp_stats *rs;
14901498

1491-
reti->rtp = 1;
14921499
// this code is execute only once: list therefore must be empty
14931500
assert(*payload_types == NULL);
14941501
*payload_types = g_hash_table_get_values(stream->rtp_stats);

daemon/rtcp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ int rtcp_avp2savp(str *s, struct crypto_context *c, struct ssrc_ctx *ssrc_ctx) {
897897
int rtcp_savp2avp(str *s, struct crypto_context *c, struct ssrc_ctx *ssrc_ctx) {
898898
struct rtcp_packet *rtcp;
899899
str payload, to_auth, to_decrypt, auth_tag;
900-
uint32_t idx, *idx_p;
900+
uint32_t idx;
901901
char hmac[20];
902902
const char *err;
903903

@@ -923,8 +923,8 @@ int rtcp_savp2avp(str *s, struct crypto_context *c, struct ssrc_ctx *ssrc_ctx) {
923923
if (to_decrypt.len < sizeof(idx))
924924
goto error;
925925
to_decrypt.len -= sizeof(idx);
926-
idx_p = (void *) to_decrypt.s + to_decrypt.len;
927-
idx = ntohl(*idx_p);
926+
memcpy(&idx, to_decrypt.s + to_decrypt.len, sizeof(idx));
927+
idx = ntohl(idx);
928928

929929
crypto_debug_printf(", idx %" PRIu32, idx);
930930

kernel-module/xt_RTPENGINE.c

Lines changed: 145 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,8 @@ static int proc_list_show(struct seq_file *f, void *v) {
17581758
seq_printf(f, " SSRC-tracking");
17591759
if (g->target.do_intercept)
17601760
seq_printf(f, " intercept");
1761+
if (g->target.rtcp_fb_fw)
1762+
seq_printf(f, " forward-RTCP-FB");
17611763
seq_printf(f, "\n");
17621764

17631765
for (i = 0; i < g->target.num_destinations; i++) {
@@ -3595,7 +3597,7 @@ static int stream_packet(struct rtpengine_table *t, const struct rtpengine_packe
35953597
if (!len) /* can't have empty packets */
35963598
return -EINVAL;
35973599

3598-
DBG("received %u bytes of data from userspace\n", len);
3600+
DBG("received %zu bytes of data from userspace\n", len);
35993601

36003602
err = -ENOENT;
36013603
stream = get_stream_lock(NULL, info->stream_idx);
@@ -3643,6 +3645,20 @@ static int target_find_ssrc(struct rtpengine_target *g, uint32_t ssrc) {
36433645
return -2;
36443646
}
36453647

3648+
static void parse_rtcp(struct rtp_parsed *rtp, struct sk_buff *skb) {
3649+
rtp->ok = 0;
3650+
rtp->rtcp = 0;
3651+
3652+
if (skb->len < sizeof(struct rtcp_header))
3653+
return;
3654+
3655+
rtp->rtcp_header = (void *) skb->data;
3656+
rtp->header_len = sizeof(struct rtcp_header);
3657+
rtp->payload = skb->data + sizeof(struct rtcp_header);
3658+
rtp->payload_len = skb->len - sizeof(struct rtcp_header);
3659+
rtp->rtcp = 1;
3660+
}
3661+
36463662
static int table_send_rtcp(struct rtpengine_table *t, const struct rtpengine_send_packet_info *info, size_t len)
36473663
{
36483664
struct rtpengine_target *g;
@@ -3690,14 +3706,8 @@ static int table_send_rtcp(struct rtpengine_table *t, const struct rtpengine_sen
36903706
skb_reserve(skb, MAX_HEADER);
36913707
memcpy(skb_put(skb, len), data, len);
36923708

3693-
// rudimentarily set up header
3694-
memset(&rtp, 0, sizeof(rtp));
3695-
if (len >= sizeof(struct rtcp_header)) {
3696-
rtp.rtcp_header = (void *) skb->data;
3697-
rtp.header_len = sizeof(struct rtcp_header);
3698-
rtp.payload = skb->data + sizeof(struct rtcp_header);
3699-
rtp.payload_len = skb->len - sizeof(struct rtcp_header);
3700-
rtp.rtcp = 1;
3709+
parse_rtcp(&rtp, skb);
3710+
if (rtp.rtcp) {
37013711
ssrc_idx = target_find_ssrc(g, rtp.rtcp_header->ssrc);
37023712
if (ssrc_idx == -2) {
37033713
kfree_skb(skb);
@@ -4494,6 +4504,61 @@ static int srtp_auth_validate(struct re_crypto_context *c,
44944504
ok:
44954505
return 0;
44964506
}
4507+
static int srtcp_auth_validate(struct re_crypto_context *c,
4508+
struct rtpengine_srtp *s, struct rtp_parsed *r,
4509+
uint64_t *pkt_idx_p)
4510+
{
4511+
uint32_t idx;
4512+
unsigned char *auth_tag = NULL;
4513+
unsigned char hmac[20];
4514+
4515+
if (!c->cipher->decrypt_rtcp)
4516+
return 0;
4517+
4518+
if (s->rtcp_auth_tag_len) {
4519+
// we have an auth tag to verify
4520+
if (s->hmac == REH_NULL)
4521+
return -1;
4522+
if (!c->hmac)
4523+
return -1;
4524+
if (!c->shash)
4525+
return -1;
4526+
4527+
// extract auth tag
4528+
if (r->payload_len < s->rtcp_auth_tag_len)
4529+
return -1;
4530+
auth_tag = r->payload + r->payload_len - s->rtcp_auth_tag_len;
4531+
r->payload_len -= s->rtcp_auth_tag_len;
4532+
}
4533+
4534+
// skip MKI
4535+
if (r->payload_len < s->mki_len)
4536+
return -1;
4537+
r->payload_len -= s->mki_len;
4538+
4539+
// extract index
4540+
if (r->payload_len < sizeof(idx))
4541+
return -1;
4542+
memcpy(&idx, r->payload + r->payload_len - sizeof(idx), sizeof(idx));
4543+
idx = ntohl(idx);
4544+
4545+
if (auth_tag) {
4546+
if (srtcp_hash(hmac, c, s, r, idx))
4547+
return -1;
4548+
if (memcmp(auth_tag, hmac, s->rtcp_auth_tag_len))
4549+
return -1;
4550+
}
4551+
4552+
r->payload_len -= sizeof(idx);
4553+
4554+
if ((idx & 0x80000000ULL)) {
4555+
*pkt_idx_p = idx & ~0x80000000ULL;
4556+
return 1; // decrypt
4557+
}
4558+
4559+
*pkt_idx_p = idx;
4560+
return 0;
4561+
}
44974562

44984563

44994564
/* XXX shared code */
@@ -4898,6 +4963,37 @@ static inline int is_muxed_rtcp(struct sk_buff *skb) {
48984963
return 0;
48994964
return 1;
49004965
}
4966+
static inline int is_rtcp_fb_packet(struct sk_buff *skb) {
4967+
unsigned char m_pt;
4968+
size_t left = skb->len;
4969+
size_t offset = 0;
4970+
unsigned int packets = 0;
4971+
uint16_t len;
4972+
4973+
while (1) {
4974+
if (left < 8) // minimum RTCP size
4975+
return 0;
4976+
m_pt = skb->data[offset + 1];
4977+
// only RTPFB and PSFB
4978+
if (m_pt != 205 && m_pt != 206)
4979+
return 0;
4980+
4981+
// length check
4982+
len = (((unsigned char) skb->data[offset + 2]) << 8)
4983+
| ((unsigned char) skb->data[offset + 3]);
4984+
len++;
4985+
len <<= 2;
4986+
if (len > left) // invalid
4987+
return 0;
4988+
4989+
left -= len;
4990+
offset += len;
4991+
4992+
if (packets++ >= 8) // limit number of compound packets
4993+
return 0;
4994+
}
4995+
return 1;
4996+
}
49014997
static inline int is_stun(struct rtpengine_target *g, unsigned int datalen, unsigned char *skb_data) {
49024998
uint32_t *u32;
49034999
if (!g->target.stun)
@@ -5195,6 +5291,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
51955291
unsigned long flags;
51965292
unsigned int i;
51975293
unsigned int start_idx, end_idx;
5294+
int is_rtcp;
51985295

51995296
#if (RE_HAS_MEASUREDELAY)
52005297
uint64_t starttime, endtime, delay;
@@ -5228,9 +5325,9 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
52285325
}
52295326
_r_unlock(&g->outputs_lock, flags);
52305327

5231-
DBG("target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr));
5232-
DBG("target decrypt hmac and cipher are %s and %s", g->decrypt.hmac->name,
5233-
g->decrypt.cipher->name);
5328+
DBG("target found, local " MIPF "\n", MIPP(g->target.local));
5329+
DBG("target decrypt RTP hmac and cipher are %s and %s", g->decrypt_rtp.hmac->name,
5330+
g->decrypt_rtp.cipher->name);
52345331

52355332
if (is_stun(g, datalen, skb->data))
52365333
goto out;
@@ -5259,19 +5356,33 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
52595356

52605357
// RTP processing
52615358
rtp.ok = 0;
5359+
rtp.rtcp = 0;
5360+
is_rtcp = 0;
52625361
if (g->target.rtp) {
52635362
if (g->target.rtcp) {
52645363
if (g->target.rtcp_mux) {
52655364
if (is_muxed_rtcp(skb))
5266-
goto out; // pass to userspace
5365+
is_rtcp = 1;
52675366
}
52685367
else
5269-
goto out; // RTCP only
5368+
is_rtcp = 1;
5369+
}
5370+
5371+
if (!is_rtcp) {
5372+
parse_rtp(&rtp, skb);
5373+
if (!rtp.ok && g->target.rtp_only)
5374+
goto out; // pass to userspace
52705375
}
5376+
else {
5377+
if (g->target.rtcp_fb_fw && is_rtcp_fb_packet(skb))
5378+
; // forward and then drop
5379+
else
5380+
goto out; // just pass to userspace
52715381

5272-
parse_rtp(&rtp, skb);
5273-
if (!rtp.ok && g->target.rtp_only)
5274-
goto out; // pass to userspace
5382+
parse_rtcp(&rtp, skb);
5383+
if (!rtp.rtcp)
5384+
goto out;
5385+
}
52755386
}
52765387
if (rtp.ok) {
52775388
// RTP ok
@@ -5312,6 +5423,20 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
53125423
rtp.payload[12], rtp.payload[13], rtp.payload[14], rtp.payload[15],
53135424
rtp.payload[16], rtp.payload[17], rtp.payload[18], rtp.payload[19]);
53145425
}
5426+
else if (is_rtcp && rtp.rtcp) {
5427+
pkt_idx = 0;
5428+
err = srtcp_auth_validate(&g->decrypt_rtcp, &g->target.decrypt, &rtp, &pkt_idx);
5429+
errstr = "SRTCP authentication tag mismatch";
5430+
if (err == -1)
5431+
goto out_error;
5432+
if (err == 1) {
5433+
// decrypt
5434+
errstr = "SRTCP decryption failed";
5435+
if (srtcp_decrypt(&g->decrypt_rtcp, &g->target.decrypt, &rtp, pkt_idx))
5436+
goto out_error;
5437+
}
5438+
skb_trim(skb, rtp.header_len + rtp.payload_len);
5439+
}
53155440

53165441
if (g->target.do_intercept) {
53175442
DBG("do_intercept is set\n");
@@ -5338,6 +5463,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
53385463

53395464
for (i = start_idx; i < end_idx; i++) {
53405465
struct rtpengine_output *o = &g->outputs[i];
5466+
DBG("output src " MIPF " -> dst " MIPF "\n", MIPP(o->output.src_addr), MIPP(o->output.dst_addr));
53415467
// do we need a copy?
53425468
if (i == (end_idx - 1)) {
53435469
skb2 = skb; // last iteration - use original
@@ -5356,7 +5482,8 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
53565482
}
53575483
// adjust RTP pointers
53585484
rtp2 = rtp;
5359-
rtp2.rtp_header = (void *) (((char *) rtp2.rtp_header) + offset);
5485+
if (rtp.rtp_header)
5486+
rtp2.rtp_header = (void *) (((char *) rtp2.rtp_header) + offset);
53605487
rtp2.payload = (void *) (((char *) rtp2.payload) + offset);
53615488

53625489
datalen_out = skb2->len;

kernel-module/xt_RTPENGINE.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct rtpengine_target_info {
125125
rtp_only:1,
126126
track_ssrc:1,
127127
rtcp:1,
128+
rtcp_fb_fw:1,
128129
do_intercept:1,
129130
pt_filter:1,
130131
non_forwarding:1, // empty src/dst addr

0 commit comments

Comments
 (0)