提交 876c2731 编写于 作者: F Florian Westphal 提交者: Pablo Neira Ayuso

netfilter: nf_conntrack_sip: allow duplicate SDP expectations

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: NCallum Sinclair <Callum.Sinclair@alliedtelesis.co.nz>
Tested-by: NCallum Sinclair <Callum.Sinclair@alliedtelesis.co.nz>
Signed-off-by: NFlorian Westphal <fw@strlen.de>
Signed-off-by: NPablo Neira Ayuso <pablo@netfilter.org>
上级 a2ac9990
...@@ -252,7 +252,7 @@ static inline int expect_clash(const struct nf_conntrack_expect *a, ...@@ -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, static inline int expect_matches(const struct nf_conntrack_expect *a,
const struct nf_conntrack_expect *b) 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_equal(&a->tuple, &b->tuple) &&
nf_ct_tuple_mask_equal(&a->mask, &b->mask) && nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) && net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
...@@ -421,6 +421,9 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) ...@@ -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); h = nf_ct_expect_dst_hash(net, &expect->tuple);
hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) { hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
if (expect_matches(i, expect)) { if (expect_matches(i, expect)) {
if (i->class != expect->class)
return -EALREADY;
if (nf_ct_remove_expect(i)) if (nf_ct_remove_expect(i))
break; break;
} else if (expect_clash(i, expect)) { } else if (expect_clash(i, expect)) {
......
...@@ -938,11 +938,19 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, ...@@ -938,11 +938,19 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
datalen, rtp_exp, rtcp_exp, datalen, rtp_exp, rtcp_exp,
mediaoff, medialen, daddr); mediaoff, medialen, daddr);
else { else {
if (nf_ct_expect_related(rtp_exp) == 0) { /* -EALREADY handling works around end-points that send
if (nf_ct_expect_related(rtcp_exp) != 0) * SDP messages with identical port but different media type,
nf_ct_unexpect_related(rtp_exp); * we pretend expectation was set up.
else */
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; ret = NF_ACCEPT;
else if (errp == 0)
nf_ct_unexpect_related(rtp_exp);
} }
} }
nf_ct_expect_put(rtcp_exp); nf_ct_expect_put(rtcp_exp);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册