aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-25 23:25:49 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-25 23:25:49 -0400
commita9c1d35917c0c95c8f95a8e497fb91e301419693 (patch)
tree5727524a97424f03882e4b37c49073ea4270d8a6 /net
parentd901a9369e6e7d07a7eb4ddb315c6fcbaf8b24d3 (diff)
[NETFILTER]: nf_conntrack_sip: create RTCP expectations
Create expectations for the RTCP connections in addition to RTP connections. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c42
-rw-r--r--net/netfilter/nf_conntrack_sip.c58
2 files changed, 64 insertions, 36 deletions
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 4b85e21a2a4a..f73ab4883b75 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -364,7 +364,8 @@ static unsigned int mangle_sdp(struct sk_buff *skb,
364 Mangle it, and change the expectation to match the new version. */ 364 Mangle it, and change the expectation to match the new version. */
365static unsigned int ip_nat_sdp(struct sk_buff *skb, 365static unsigned int ip_nat_sdp(struct sk_buff *skb,
366 const char **dptr, unsigned int *datalen, 366 const char **dptr, unsigned int *datalen,
367 struct nf_conntrack_expect *exp) 367 struct nf_conntrack_expect *rtp_exp,
368 struct nf_conntrack_expect *rtcp_exp)
368{ 369{
369 enum ip_conntrack_info ctinfo; 370 enum ip_conntrack_info ctinfo;
370 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 371 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
@@ -375,31 +376,40 @@ static unsigned int ip_nat_sdp(struct sk_buff *skb,
375 /* Connection will come from reply */ 376 /* Connection will come from reply */
376 if (ct->tuplehash[dir].tuple.src.u3.ip == 377 if (ct->tuplehash[dir].tuple.src.u3.ip ==
377 ct->tuplehash[!dir].tuple.dst.u3.ip) 378 ct->tuplehash[!dir].tuple.dst.u3.ip)
378 newip = exp->tuple.dst.u3.ip; 379 newip = rtp_exp->tuple.dst.u3.ip;
379 else 380 else
380 newip = ct->tuplehash[!dir].tuple.dst.u3.ip; 381 newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
381 382
382 exp->saved_ip = exp->tuple.dst.u3.ip; 383 rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip;
383 exp->tuple.dst.u3.ip = newip; 384 rtp_exp->tuple.dst.u3.ip = newip;
384 exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port; 385 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
385 exp->dir = !dir; 386 rtp_exp->dir = !dir;
386 387 rtp_exp->expectfn = ip_nat_sip_expected;
387 /* When you see the packet, we need to NAT it the same as the 388
388 this one. */ 389 rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip;
389 exp->expectfn = ip_nat_sip_expected; 390 rtcp_exp->tuple.dst.u3.ip = newip;
390 391 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
391 /* Try to get same port: if not, try to change it. */ 392 rtcp_exp->dir = !dir;
392 for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) { 393 rtcp_exp->expectfn = ip_nat_sip_expected;
393 exp->tuple.dst.u.udp.port = htons(port); 394
394 if (nf_ct_expect_related(exp) == 0) 395 /* Try to get same pair of ports: if not, try to change them. */
396 for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
397 port != 0; port += 2) {
398 rtp_exp->tuple.dst.u.udp.port = htons(port);
399 if (nf_ct_expect_related(rtp_exp) != 0)
400 continue;
401 rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
402 if (nf_ct_expect_related(rtcp_exp) == 0)
395 break; 403 break;
404 nf_ct_unexpect_related(rtp_exp);
396 } 405 }
397 406
398 if (port == 0) 407 if (port == 0)
399 return NF_DROP; 408 return NF_DROP;
400 409
401 if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr, datalen)) { 410 if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr, datalen)) {
402 nf_ct_unexpect_related(exp); 411 nf_ct_unexpect_related(rtp_exp);
412 nf_ct_unexpect_related(rtcp_exp);
403 return NF_DROP; 413 return NF_DROP;
404 } 414 }
405 return NF_ACCEPT; 415 return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 813aa8c67e4c..217262e23403 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -63,7 +63,9 @@ EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
63unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, 63unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
64 const char **dptr, 64 const char **dptr,
65 unsigned int *datalen, 65 unsigned int *datalen,
66 struct nf_conntrack_expect *exp) __read_mostly; 66 struct nf_conntrack_expect *rtp_exp,
67 struct nf_conntrack_expect *rtcp_exp)
68 __read_mostly;
67EXPORT_SYMBOL_GPL(nf_nat_sdp_hook); 69EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
68 70
69static int string_len(const struct nf_conn *ct, const char *dptr, 71static int string_len(const struct nf_conn *ct, const char *dptr,
@@ -659,18 +661,20 @@ static void flush_expectations(struct nf_conn *ct, bool media)
659 spin_unlock_bh(&nf_conntrack_lock); 661 spin_unlock_bh(&nf_conntrack_lock);
660} 662}
661 663
662static int set_expected_rtp(struct sk_buff *skb, 664static int set_expected_rtp_rtcp(struct sk_buff *skb,
663 const char **dptr, unsigned int *datalen, 665 const char **dptr, unsigned int *datalen,
664 union nf_inet_addr *daddr, __be16 port) 666 union nf_inet_addr *daddr, __be16 port)
665{ 667{
666 struct nf_conntrack_expect *exp; 668 struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp;
667 enum ip_conntrack_info ctinfo; 669 enum ip_conntrack_info ctinfo;
668 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 670 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
669 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 671 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
670 union nf_inet_addr *saddr; 672 union nf_inet_addr *saddr;
671 struct nf_conntrack_tuple tuple; 673 struct nf_conntrack_tuple tuple;
672 int family = ct->tuplehash[!dir].tuple.src.l3num; 674 int family = ct->tuplehash[!dir].tuple.src.l3num;
673 int skip_expect = 0, ret; 675 int skip_expect = 0, ret = NF_DROP;
676 u_int16_t base_port;
677 __be16 rtp_port, rtcp_port;
674 typeof(nf_nat_sdp_hook) nf_nat_sdp; 678 typeof(nf_nat_sdp_hook) nf_nat_sdp;
675 679
676 saddr = NULL; 680 saddr = NULL;
@@ -704,23 +708,37 @@ static int set_expected_rtp(struct sk_buff *skb,
704 if (skip_expect) 708 if (skip_expect)
705 return NF_ACCEPT; 709 return NF_ACCEPT;
706 710
707 exp = nf_ct_expect_alloc(ct); 711 base_port = ntohs(tuple.dst.u.udp.port) & ~1;
708 if (exp == NULL) 712 rtp_port = htons(base_port);
709 return NF_DROP; 713 rtcp_port = htons(base_port + 1);
710 nf_ct_expect_init(exp, SIP_EXPECT_AUDIO, family, saddr, daddr, 714
711 IPPROTO_UDP, NULL, &port); 715 rtp_exp = nf_ct_expect_alloc(ct);
716 if (rtp_exp == NULL)
717 goto err1;
718 nf_ct_expect_init(rtp_exp, SIP_EXPECT_AUDIO, family, saddr, daddr,
719 IPPROTO_UDP, NULL, &rtp_port);
720
721 rtcp_exp = nf_ct_expect_alloc(ct);
722 if (rtcp_exp == NULL)
723 goto err2;
724 nf_ct_expect_init(rtcp_exp, SIP_EXPECT_AUDIO, family, saddr, daddr,
725 IPPROTO_UDP, NULL, &rtcp_port);
712 726
713 nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); 727 nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
714 if (nf_nat_sdp && ct->status & IPS_NAT_MASK) 728 if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
715 ret = nf_nat_sdp(skb, dptr, datalen, exp); 729 ret = nf_nat_sdp(skb, dptr, datalen, rtp_exp, rtcp_exp);
716 else { 730 else {
717 if (nf_ct_expect_related(exp) != 0) 731 if (nf_ct_expect_related(rtp_exp) == 0) {
718 ret = NF_DROP; 732 if (nf_ct_expect_related(rtcp_exp) != 0)
719 else 733 nf_ct_unexpect_related(rtp_exp);
720 ret = NF_ACCEPT; 734 else
735 ret = NF_ACCEPT;
736 }
721 } 737 }
722 nf_ct_expect_put(exp); 738 nf_ct_expect_put(rtcp_exp);
723 739err2:
740 nf_ct_expect_put(rtp_exp);
741err1:
724 return ret; 742 return ret;
725} 743}
726 744
@@ -758,7 +776,7 @@ static int process_sdp(struct sk_buff *skb,
758 if (port < 1024 || port > 65535) 776 if (port < 1024 || port > 65535)
759 return NF_DROP; 777 return NF_DROP;
760 778
761 return set_expected_rtp(skb, dptr, datalen, &addr, htons(port)); 779 return set_expected_rtp_rtcp(skb, dptr, datalen, &addr, htons(port));
762} 780}
763static int process_invite_response(struct sk_buff *skb, 781static int process_invite_response(struct sk_buff *skb,
764 const char **dptr, unsigned int *datalen, 782 const char **dptr, unsigned int *datalen,
@@ -1101,7 +1119,7 @@ static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1
1101 .timeout = 3 * 60, 1119 .timeout = 3 * 60,
1102 }, 1120 },
1103 [SIP_EXPECT_AUDIO] = { 1121 [SIP_EXPECT_AUDIO] = {
1104 .max_expected = IP_CT_DIR_MAX, 1122 .max_expected = 2 * IP_CT_DIR_MAX,
1105 .timeout = 3 * 60, 1123 .timeout = 3 * 60,
1106 }, 1124 },
1107}; 1125};