[NETFILTER]: nf_conntrack_sip: allow media expectations with wildcard source address

Media streams can come from anywhere, add a module parameter which
controls whether wildcard expectations or expectations between the
two signalling endpoints are created.

Since the same media description sent on multiple connections may
results in multiple identical expections when using a wildcard source,
we need to check whether a similar expectation already exists for a
different connection before attempting to register it.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Patrick McHardy 2008-03-25 20:25:32 -07:00 committed by David S. Miller
parent 0f32a40fc9
commit d901a9369e
1 changed files with 41 additions and 4 deletions

View File

@ -42,6 +42,11 @@ module_param(sip_direct_signalling, int, 0600);
MODULE_PARM_DESC(sip_direct_signalling, "expect incoming calls from registrar "
"only (default 1)");
static int sip_direct_media __read_mostly = 1;
module_param(sip_direct_media, int, 0600);
MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
"endpoints only (default 1)");
unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
const char **dptr,
unsigned int *datalen) __read_mostly;
@ -656,21 +661,53 @@ static void flush_expectations(struct nf_conn *ct, bool media)
static int set_expected_rtp(struct sk_buff *skb,
const char **dptr, unsigned int *datalen,
union nf_inet_addr *addr, __be16 port)
union nf_inet_addr *daddr, __be16 port)
{
struct nf_conntrack_expect *exp;
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
union nf_inet_addr *saddr;
struct nf_conntrack_tuple tuple;
int family = ct->tuplehash[!dir].tuple.src.l3num;
int ret;
int skip_expect = 0, ret;
typeof(nf_nat_sdp_hook) nf_nat_sdp;
saddr = NULL;
if (sip_direct_media) {
if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3))
return NF_ACCEPT;
saddr = &ct->tuplehash[!dir].tuple.src.u3;
}
/* We need to check whether the registration exists before attempting
* to register it since we can see the same media description multiple
* times on different connections in case multiple endpoints receive
* the same call.
*/
memset(&tuple, 0, sizeof(tuple));
if (saddr)
tuple.src.u3 = *saddr;
tuple.src.l3num = family;
tuple.dst.protonum = IPPROTO_UDP;
tuple.dst.u3 = *daddr;
tuple.dst.u.udp.port = port;
rcu_read_lock();
exp = __nf_ct_expect_find(&tuple);
if (exp && exp->master != ct &&
nfct_help(exp->master)->helper == nfct_help(ct)->helper &&
exp->class == SIP_EXPECT_AUDIO)
skip_expect = 1;
rcu_read_unlock();
if (skip_expect)
return NF_ACCEPT;
exp = nf_ct_expect_alloc(ct);
if (exp == NULL)
return NF_DROP;
nf_ct_expect_init(exp, SIP_EXPECT_AUDIO, family,
&ct->tuplehash[!dir].tuple.src.u3, addr,
nf_ct_expect_init(exp, SIP_EXPECT_AUDIO, family, saddr, daddr,
IPPROTO_UDP, NULL, &port);
nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);