|
|
|
@ -270,7 +270,7 @@ struct re_crypto_context { |
|
|
|
unsigned char session_key[32]; |
|
|
|
unsigned char session_salt[14]; |
|
|
|
unsigned char session_auth_key[20]; |
|
|
|
uint32_t roc; |
|
|
|
uint32_t roc[RTPE_NUM_SSRC_TRACKING]; |
|
|
|
struct crypto_cipher *tfm[2]; |
|
|
|
struct crypto_shash *shash; |
|
|
|
struct crypto_aead *aead; |
|
|
|
@ -304,7 +304,7 @@ struct rtpengine_target { |
|
|
|
struct rtpengine_stats_a stats; |
|
|
|
struct rtpengine_rtp_stats_a rtp_stats[RTPE_NUM_PAYLOAD_TYPES]; |
|
|
|
spinlock_t ssrc_stats_lock; |
|
|
|
struct rtpengine_ssrc_stats ssrc_stats; |
|
|
|
struct rtpengine_ssrc_stats ssrc_stats[RTPE_NUM_SSRC_TRACKING]; |
|
|
|
|
|
|
|
struct re_crypto_context decrypt; |
|
|
|
|
|
|
|
@ -1427,7 +1427,8 @@ static ssize_t proc_blist_read(struct file *f, char __user *b, size_t l, loff_t |
|
|
|
} |
|
|
|
|
|
|
|
spin_lock_irqsave(&g->decrypt.lock, flags); |
|
|
|
opp->target.decrypt.last_index = g->target.decrypt.last_index; |
|
|
|
for (i = 0; i < ARRAY_SIZE(opp->target.decrypt.last_index); i++) |
|
|
|
opp->target.decrypt.last_index[i] = g->target.decrypt.last_index[i]; |
|
|
|
spin_unlock_irqrestore(&g->decrypt.lock, flags); |
|
|
|
|
|
|
|
_r_lock(&g->outputs_lock, flags); |
|
|
|
@ -1588,7 +1589,14 @@ static void proc_list_crypto_print(struct seq_file *f, struct re_crypto_context |
|
|
|
seq_printf(f, "%02x", c->session_auth_key[i]); |
|
|
|
seq_printf(f, "\n"); |
|
|
|
|
|
|
|
seq_printf(f, " ROC: %u\n", (unsigned int) c->roc); |
|
|
|
seq_printf(f, " ROC:"); |
|
|
|
for (i = 0; i < ARRAY_SIZE(c->roc); i++) { |
|
|
|
if (i == 0) |
|
|
|
seq_printf(f, " %u", (unsigned int) c->roc[i]); |
|
|
|
else |
|
|
|
seq_printf(f, ", %u", (unsigned int) c->roc[i]); |
|
|
|
} |
|
|
|
seq_printf(f, "\n"); |
|
|
|
|
|
|
|
if (s->mki_len) |
|
|
|
seq_printf(f, " MKI: length %u, %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x...\n", |
|
|
|
@ -1639,8 +1647,18 @@ static int proc_list_show(struct seq_file *f, void *v) { |
|
|
|
seq_printf(f, " %u bytes replacement payload\n", |
|
|
|
g->target.payload_types[i].replace_pattern_len); |
|
|
|
} |
|
|
|
if (g->target.ssrc) |
|
|
|
seq_printf(f, " SSRC in: %lx\n", (unsigned long) ntohl(g->target.ssrc)); |
|
|
|
|
|
|
|
seq_printf(f, " SSRC in:"); |
|
|
|
for (i = 0; i < ARRAY_SIZE(g->target.ssrc); i++) { |
|
|
|
if (!g->target.ssrc[i]) |
|
|
|
break; |
|
|
|
if (i == 0) |
|
|
|
seq_printf(f, " %lx", (unsigned long) ntohl(g->target.ssrc[i])); |
|
|
|
else |
|
|
|
seq_printf(f, ", %lx", (unsigned long) ntohl(g->target.ssrc[i])); |
|
|
|
} |
|
|
|
seq_printf(f, "\n"); |
|
|
|
|
|
|
|
proc_list_crypto_print(f, &g->decrypt, &g->target.decrypt, "decryption"); |
|
|
|
if (g->target.rtcp_mux) |
|
|
|
seq_printf(f, " option: rtcp-mux\n"); |
|
|
|
@ -1662,8 +1680,18 @@ static int proc_list_show(struct seq_file *f, void *v) { |
|
|
|
seq_printf(f, " output #%u\n", i); |
|
|
|
proc_list_addr_print(f, "src", &o->output.src_addr); |
|
|
|
proc_list_addr_print(f, "dst", &o->output.dst_addr); |
|
|
|
if (o->output.ssrc_out) |
|
|
|
seq_printf(f, " SSRC out: %lx\n", (unsigned long) ntohl(o->output.ssrc_out)); |
|
|
|
|
|
|
|
seq_printf(f, " SSRC out:"); |
|
|
|
for (i = 0; i < ARRAY_SIZE(o->output.ssrc_out); i++) { |
|
|
|
if (!o->output.ssrc_out[i]) |
|
|
|
break; |
|
|
|
if (i == 0) |
|
|
|
seq_printf(f, " %lx", (unsigned long) ntohl(o->output.ssrc_out[i])); |
|
|
|
else |
|
|
|
seq_printf(f, ", %lx", (unsigned long) ntohl(o->output.ssrc_out[i])); |
|
|
|
} |
|
|
|
seq_printf(f, "\n"); |
|
|
|
|
|
|
|
proc_list_crypto_print(f, &o->encrypt, &o->output.encrypt, "encryption"); |
|
|
|
} |
|
|
|
|
|
|
|
@ -1753,19 +1781,23 @@ static struct re_dest_addr *find_dest_addr(const struct re_dest_addr_hash *h, co |
|
|
|
|
|
|
|
static int table_get_target_stats(struct rtpengine_table *t, struct rtpengine_stats_info *i, int reset) { |
|
|
|
struct rtpengine_target *g; |
|
|
|
unsigned int u; |
|
|
|
|
|
|
|
g = get_target(t, &i->local); |
|
|
|
if (!g) |
|
|
|
return -ENOENT; |
|
|
|
|
|
|
|
i->ssrc = g->target.ssrc; |
|
|
|
spin_lock(&g->ssrc_stats_lock); |
|
|
|
i->ssrc_stats = g->ssrc_stats; |
|
|
|
|
|
|
|
if (reset) { |
|
|
|
g->ssrc_stats.basic_stats.packets = 0; |
|
|
|
g->ssrc_stats.basic_stats.bytes = 0; |
|
|
|
g->ssrc_stats.total_lost = 0; |
|
|
|
for (u = 0; u < RTPE_NUM_SSRC_TRACKING; u++) { |
|
|
|
i->ssrc[u] = g->target.ssrc[u]; |
|
|
|
i->ssrc_stats[u] = g->ssrc_stats[u]; |
|
|
|
|
|
|
|
if (reset) { |
|
|
|
g->ssrc_stats[u].basic_stats.packets = 0; |
|
|
|
g->ssrc_stats[u].basic_stats.bytes = 0; |
|
|
|
g->ssrc_stats[u].total_lost = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
spin_unlock(&g->ssrc_stats_lock); |
|
|
|
@ -2243,6 +2275,7 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i |
|
|
|
struct rtpengine_target *og = NULL; |
|
|
|
int err; |
|
|
|
unsigned long flags; |
|
|
|
unsigned int u; |
|
|
|
|
|
|
|
/* validation */ |
|
|
|
|
|
|
|
@ -2276,7 +2309,8 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i |
|
|
|
memcpy(&g->target, i, sizeof(*i)); |
|
|
|
crypto_context_init(&g->decrypt, &g->target.decrypt); |
|
|
|
spin_lock_init(&g->ssrc_stats_lock); |
|
|
|
g->ssrc_stats.lost_bits = -1; |
|
|
|
for (u = 0; u < RTPE_NUM_SSRC_TRACKING; u++) |
|
|
|
g->ssrc_stats[u].lost_bits = -1; |
|
|
|
rwlock_init(&g->outputs_lock); |
|
|
|
|
|
|
|
if (i->num_destinations) { |
|
|
|
@ -3777,7 +3811,7 @@ error: |
|
|
|
|
|
|
|
/* XXX shared code */ |
|
|
|
static uint64_t packet_index(struct re_crypto_context *c, |
|
|
|
struct rtpengine_srtp *s, struct rtp_header *rtp) |
|
|
|
struct rtpengine_srtp *s, struct rtp_header *rtp, int ssrc_idx) |
|
|
|
{ |
|
|
|
uint16_t seq; |
|
|
|
uint64_t index; |
|
|
|
@ -3786,17 +3820,20 @@ static uint64_t packet_index(struct re_crypto_context *c, |
|
|
|
uint32_t roc; |
|
|
|
uint32_t v; |
|
|
|
|
|
|
|
if (ssrc_idx == -1) |
|
|
|
ssrc_idx = 0; |
|
|
|
|
|
|
|
seq = ntohs(rtp->seq_num); |
|
|
|
|
|
|
|
spin_lock_irqsave(&c->lock, flags); |
|
|
|
|
|
|
|
/* rfc 3711 section 3.3.1 */ |
|
|
|
if (unlikely(!s->last_index)) |
|
|
|
s->last_index = seq; |
|
|
|
if (unlikely(!s->last_index[ssrc_idx])) |
|
|
|
s->last_index[ssrc_idx] = seq; |
|
|
|
|
|
|
|
/* rfc 3711 appendix A, modified, and sections 3.3 and 3.3.1 */ |
|
|
|
s_l = (s->last_index & 0x00000000ffffULL); |
|
|
|
roc = (s->last_index & 0xffffffff0000ULL) >> 16; |
|
|
|
s_l = (s->last_index[ssrc_idx] & 0x00000000ffffULL); |
|
|
|
roc = (s->last_index[ssrc_idx] & 0xffffffff0000ULL) >> 16; |
|
|
|
v = 0; |
|
|
|
|
|
|
|
if (s_l < 0x8000) { |
|
|
|
@ -3812,8 +3849,8 @@ static uint64_t packet_index(struct re_crypto_context *c, |
|
|
|
} |
|
|
|
|
|
|
|
index = (v << 16) | seq; |
|
|
|
s->last_index = index; |
|
|
|
c->roc = v; |
|
|
|
s->last_index[ssrc_idx] = index; |
|
|
|
c->roc[ssrc_idx] = v; |
|
|
|
|
|
|
|
spin_unlock_irqrestore(&c->lock, flags); |
|
|
|
|
|
|
|
@ -3821,13 +3858,16 @@ static uint64_t packet_index(struct re_crypto_context *c, |
|
|
|
} |
|
|
|
|
|
|
|
static void update_packet_index(struct re_crypto_context *c, |
|
|
|
struct rtpengine_srtp *s, uint64_t idx) |
|
|
|
struct rtpengine_srtp *s, uint64_t idx, int ssrc_idx) |
|
|
|
{ |
|
|
|
unsigned long flags; |
|
|
|
|
|
|
|
if (ssrc_idx == -1) |
|
|
|
ssrc_idx = 0; |
|
|
|
|
|
|
|
spin_lock_irqsave(&c->lock, flags); |
|
|
|
s->last_index = idx; |
|
|
|
c->roc = (idx >> 16); |
|
|
|
s->last_index[ssrc_idx] = idx; |
|
|
|
c->roc[ssrc_idx] = (idx >> 16); |
|
|
|
spin_unlock_irqrestore(&c->lock, flags); |
|
|
|
} |
|
|
|
|
|
|
|
@ -3919,7 +3959,7 @@ static int srtp_authenticate(struct re_crypto_context *c, |
|
|
|
|
|
|
|
static int srtp_auth_validate(struct re_crypto_context *c, |
|
|
|
struct rtpengine_srtp *s, struct rtp_parsed *r, |
|
|
|
uint64_t *pkt_idx_p) |
|
|
|
uint64_t *pkt_idx_p, int ssrc_idx) |
|
|
|
{ |
|
|
|
unsigned char *auth_tag; |
|
|
|
unsigned char hmac[20]; |
|
|
|
@ -3981,7 +4021,7 @@ static int srtp_auth_validate(struct re_crypto_context *c, |
|
|
|
|
|
|
|
ok_update: |
|
|
|
*pkt_idx_p = pkt_idx; |
|
|
|
update_packet_index(c, s, pkt_idx); |
|
|
|
update_packet_index(c, s, pkt_idx, ssrc_idx); |
|
|
|
ok: |
|
|
|
return 0; |
|
|
|
} |
|
|
|
@ -4257,9 +4297,11 @@ static struct sk_buff *intercept_skb_copy(struct sk_buff *oskb, const struct re_ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void rtp_stats(struct rtpengine_target *g, struct rtp_parsed *rtp, s64 arrival_time, int pt_idx) { |
|
|
|
static void rtp_stats(struct rtpengine_target *g, struct rtp_parsed *rtp, s64 arrival_time, int pt_idx, |
|
|
|
int ssrc_idx) |
|
|
|
{ |
|
|
|
unsigned long flags; |
|
|
|
struct rtpengine_ssrc_stats *s = &g->ssrc_stats; |
|
|
|
struct rtpengine_ssrc_stats *s = &g->ssrc_stats[ssrc_idx]; |
|
|
|
uint16_t old_seq_trunc; |
|
|
|
uint32_t last_seq; |
|
|
|
uint16_t seq_diff; |
|
|
|
@ -4351,6 +4393,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, |
|
|
|
int err; |
|
|
|
int error_nf_action = XT_CONTINUE; |
|
|
|
int rtp_pt_idx = -2; |
|
|
|
int ssrc_idx = -1; |
|
|
|
unsigned int datalen, pllen; |
|
|
|
uint32_t *u32; |
|
|
|
struct rtp_parsed rtp, rtp2; |
|
|
|
@ -4453,13 +4496,21 @@ src_check_ok: |
|
|
|
rtp_pt_idx = rtp_payload_type(rtp.header, &g->target, &g->last_pt); |
|
|
|
|
|
|
|
// Pass to userspace if SSRC has changed. |
|
|
|
errstr = "SSRC mismatch"; |
|
|
|
if (unlikely((g->target.ssrc) && (g->target.ssrc != rtp.header->ssrc))) |
|
|
|
// Look for matching SSRC index if any SSRC were given |
|
|
|
if (likely(g->target.ssrc[0])) { |
|
|
|
errstr = "SSRC mismatch"; |
|
|
|
for (ssrc_idx = 0; ssrc_idx < RTPE_NUM_SSRC_TRACKING; ssrc_idx++) { |
|
|
|
if (g->target.ssrc[ssrc_idx] == rtp.header->ssrc) |
|
|
|
goto found_ssrc; |
|
|
|
} |
|
|
|
ssrc_idx = -1; |
|
|
|
goto skip_error; |
|
|
|
found_ssrc:; |
|
|
|
} |
|
|
|
|
|
|
|
pkt_idx = packet_index(&g->decrypt, &g->target.decrypt, rtp.header); |
|
|
|
pkt_idx = packet_index(&g->decrypt, &g->target.decrypt, rtp.header, ssrc_idx); |
|
|
|
errstr = "SRTP authentication tag mismatch"; |
|
|
|
if (srtp_auth_validate(&g->decrypt, &g->target.decrypt, &rtp, &pkt_idx)) |
|
|
|
if (srtp_auth_validate(&g->decrypt, &g->target.decrypt, &rtp, &pkt_idx, ssrc_idx)) |
|
|
|
goto skip_error; |
|
|
|
|
|
|
|
// if RTP, only forward packets of known/passthrough payload types |
|
|
|
@ -4472,8 +4523,8 @@ src_check_ok: |
|
|
|
|
|
|
|
skb_trim(skb, rtp.header_len + rtp.payload_len); |
|
|
|
|
|
|
|
if (g->target.rtp_stats) |
|
|
|
rtp_stats(g, &rtp, ktime_to_us(skb->tstamp), rtp_pt_idx); |
|
|
|
if (g->target.rtp_stats && ssrc_idx != -1) |
|
|
|
rtp_stats(g, &rtp, ktime_to_us(skb->tstamp), rtp_pt_idx, ssrc_idx); |
|
|
|
|
|
|
|
DBG("packet payload decrypted as %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x...\n", |
|
|
|
rtp.payload[0], rtp.payload[1], rtp.payload[2], rtp.payload[3], |
|
|
|
@ -4540,10 +4591,10 @@ no_intercept: |
|
|
|
|
|
|
|
if (rtp2.ok) { |
|
|
|
// SSRC substitution |
|
|
|
if (g->target.transcoding && o->output.ssrc_out) |
|
|
|
rtp2.header->ssrc = o->output.ssrc_out; |
|
|
|
if (g->target.transcoding && o->output.ssrc_out && ssrc_idx != -1) |
|
|
|
rtp2.header->ssrc = o->output.ssrc_out[ssrc_idx]; |
|
|
|
|
|
|
|
pkt_idx = packet_index(&o->encrypt, &o->output.encrypt, rtp2.header); |
|
|
|
pkt_idx = packet_index(&o->encrypt, &o->output.encrypt, rtp2.header, ssrc_idx); |
|
|
|
pllen = rtp2.payload_len; |
|
|
|
srtp_encrypt(&o->encrypt, &o->output.encrypt, &rtp2, pkt_idx); |
|
|
|
srtp_authenticate(&o->encrypt, &o->output.encrypt, &rtp2, pkt_idx); |
|
|
|
|