Skip to content

Commit

Permalink
netfilter: nf_conntrack_sip: allow duplicate SDP expectations
Browse files Browse the repository at this point in the history
Callum Sinclair reported SIP IP Phone errors that he tracked down to
such phones sending session descriptions for different media types but
with same port numbers.

The expect core will only 'refresh' existing expectation if it is
from same master AND same expectation class (media type).
As expectation class is different, we get an error.

The SIP connection tracking code will then

1). drop the SDP packet
2). if an rtp expectation was already installed successfully,
    error on rtcp expectation will cancel the rtp one.

Make the expect core report back to caller when the conflict is due
to different expectation class and have SIP tracker ignore soft-error.

Reported-by: Callum Sinclair <[email protected]>
Tested-by: Callum Sinclair <[email protected]>
Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
  • Loading branch information
Florian Westphal authored and ummakynes committed Apr 9, 2018
1 parent a2ac999 commit 876c273
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
5 changes: 4 additions & 1 deletion net/netfilter/nf_conntrack_expect.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
static inline int expect_matches(const struct nf_conntrack_expect *a,
const struct nf_conntrack_expect *b)
{
return a->master == b->master && a->class == b->class &&
return a->master == b->master &&
nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
Expand Down Expand Up @@ -421,6 +421,9 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
h = nf_ct_expect_dst_hash(net, &expect->tuple);
hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
if (expect_matches(i, expect)) {
if (i->class != expect->class)
return -EALREADY;

if (nf_ct_remove_expect(i))
break;
} else if (expect_clash(i, expect)) {
Expand Down
16 changes: 12 additions & 4 deletions net/netfilter/nf_conntrack_sip.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,11 +938,19 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
datalen, rtp_exp, rtcp_exp,
mediaoff, medialen, daddr);
else {
if (nf_ct_expect_related(rtp_exp) == 0) {
if (nf_ct_expect_related(rtcp_exp) != 0)
nf_ct_unexpect_related(rtp_exp);
else
/* -EALREADY handling works around end-points that send
* SDP messages with identical port but different media type,
* we pretend expectation was set up.
*/
int errp = nf_ct_expect_related(rtp_exp);

if (errp == 0 || errp == -EALREADY) {
int errcp = nf_ct_expect_related(rtcp_exp);

if (errcp == 0 || errcp == -EALREADY)
ret = NF_ACCEPT;
else if (errp == 0)
nf_ct_unexpect_related(rtp_exp);
}
}
nf_ct_expect_put(rtcp_exp);
Expand Down

0 comments on commit 876c273

Please sign in to comment.