@@ -1758,6 +1758,8 @@ static int proc_list_show(struct seq_file *f, void *v) {
1758
1758
seq_printf (f , " SSRC-tracking" );
1759
1759
if (g -> target .do_intercept )
1760
1760
seq_printf (f , " intercept" );
1761
+ if (g -> target .rtcp_fb_fw )
1762
+ seq_printf (f , " forward-RTCP-FB" );
1761
1763
seq_printf (f , "\n" );
1762
1764
1763
1765
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
3595
3597
if (!len ) /* can't have empty packets */
3596
3598
return - EINVAL ;
3597
3599
3598
- DBG ("received %u bytes of data from userspace\n" , len );
3600
+ DBG ("received %zu bytes of data from userspace\n" , len );
3599
3601
3600
3602
err = - ENOENT ;
3601
3603
stream = get_stream_lock (NULL , info -> stream_idx );
@@ -3643,6 +3645,20 @@ static int target_find_ssrc(struct rtpengine_target *g, uint32_t ssrc) {
3643
3645
return -2 ;
3644
3646
}
3645
3647
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
+
3646
3662
static int table_send_rtcp (struct rtpengine_table * t , const struct rtpengine_send_packet_info * info , size_t len )
3647
3663
{
3648
3664
struct rtpengine_target * g ;
@@ -3690,14 +3706,8 @@ static int table_send_rtcp(struct rtpengine_table *t, const struct rtpengine_sen
3690
3706
skb_reserve (skb , MAX_HEADER );
3691
3707
memcpy (skb_put (skb , len ), data , len );
3692
3708
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 ) {
3701
3711
ssrc_idx = target_find_ssrc (g , rtp .rtcp_header -> ssrc );
3702
3712
if (ssrc_idx == -2 ) {
3703
3713
kfree_skb (skb );
@@ -4494,6 +4504,61 @@ static int srtp_auth_validate(struct re_crypto_context *c,
4494
4504
ok :
4495
4505
return 0 ;
4496
4506
}
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
+ }
4497
4562
4498
4563
4499
4564
/* XXX shared code */
@@ -4898,6 +4963,37 @@ static inline int is_muxed_rtcp(struct sk_buff *skb) {
4898
4963
return 0 ;
4899
4964
return 1 ;
4900
4965
}
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
+ }
4901
4997
static inline int is_stun (struct rtpengine_target * g , unsigned int datalen , unsigned char * skb_data ) {
4902
4998
uint32_t * u32 ;
4903
4999
if (!g -> target .stun )
@@ -5195,6 +5291,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
5195
5291
unsigned long flags ;
5196
5292
unsigned int i ;
5197
5293
unsigned int start_idx , end_idx ;
5294
+ int is_rtcp ;
5198
5295
5199
5296
#if (RE_HAS_MEASUREDELAY )
5200
5297
uint64_t starttime , endtime , delay ;
@@ -5228,9 +5325,9 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
5228
5325
}
5229
5326
_r_unlock (& g -> outputs_lock , flags );
5230
5327
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 );
5234
5331
5235
5332
if (is_stun (g , datalen , skb -> data ))
5236
5333
goto out ;
@@ -5259,19 +5356,33 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
5259
5356
5260
5357
// RTP processing
5261
5358
rtp .ok = 0 ;
5359
+ rtp .rtcp = 0 ;
5360
+ is_rtcp = 0 ;
5262
5361
if (g -> target .rtp ) {
5263
5362
if (g -> target .rtcp ) {
5264
5363
if (g -> target .rtcp_mux ) {
5265
5364
if (is_muxed_rtcp (skb ))
5266
- goto out ; // pass to userspace
5365
+ is_rtcp = 1 ;
5267
5366
}
5268
5367
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
5270
5375
}
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
5271
5381
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
+ }
5275
5386
}
5276
5387
if (rtp .ok ) {
5277
5388
// RTP ok
@@ -5312,6 +5423,20 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
5312
5423
rtp .payload [12 ], rtp .payload [13 ], rtp .payload [14 ], rtp .payload [15 ],
5313
5424
rtp .payload [16 ], rtp .payload [17 ], rtp .payload [18 ], rtp .payload [19 ]);
5314
5425
}
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
+ }
5315
5440
5316
5441
if (g -> target .do_intercept ) {
5317
5442
DBG ("do_intercept is set\n" );
@@ -5338,6 +5463,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
5338
5463
5339
5464
for (i = start_idx ; i < end_idx ; i ++ ) {
5340
5465
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 ));
5341
5467
// do we need a copy?
5342
5468
if (i == (end_idx - 1 )) {
5343
5469
skb2 = skb ; // last iteration - use original
@@ -5356,7 +5482,8 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t,
5356
5482
}
5357
5483
// adjust RTP pointers
5358
5484
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 );
5360
5487
rtp2 .payload = (void * ) (((char * ) rtp2 .payload ) + offset );
5361
5488
5362
5489
datalen_out = skb2 -> len ;
0 commit comments