netfilter: xt_socket: use IP early demux

With IP early demux added in linux-3.6, we perform TCP lookup in IP
layer before iptables hooks.

We can avoid doing a second lookup in xt_socket.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Eric Dumazet 2013-05-22 11:01:06 +00:00 committed by Pablo Neira Ayuso
parent 27e7190efd
commit 00028aa370
1 changed files with 16 additions and 10 deletions

View File

@ -107,7 +107,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
{ {
const struct iphdr *iph = ip_hdr(skb); const struct iphdr *iph = ip_hdr(skb);
struct udphdr _hdr, *hp = NULL; struct udphdr _hdr, *hp = NULL;
struct sock *sk; struct sock *sk = skb->sk;
__be32 uninitialized_var(daddr), uninitialized_var(saddr); __be32 uninitialized_var(daddr), uninitialized_var(saddr);
__be16 uninitialized_var(dport), uninitialized_var(sport); __be16 uninitialized_var(dport), uninitialized_var(sport);
u8 uninitialized_var(protocol); u8 uninitialized_var(protocol);
@ -155,9 +155,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
} }
#endif #endif
sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol, if (!sk)
saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY); sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
if (sk != NULL) { saddr, daddr, sport, dport,
par->in, NFT_LOOKUP_ANY);
if (sk) {
bool wildcard; bool wildcard;
bool transparent = true; bool transparent = true;
@ -173,7 +175,8 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
(sk->sk_state == TCP_TIME_WAIT && (sk->sk_state == TCP_TIME_WAIT &&
inet_twsk(sk)->tw_transparent)); inet_twsk(sk)->tw_transparent));
xt_socket_put_sk(sk); if (sk != skb->sk)
xt_socket_put_sk(sk);
if (wildcard || !transparent) if (wildcard || !transparent)
sk = NULL; sk = NULL;
@ -260,7 +263,7 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
{ {
struct ipv6hdr *iph = ipv6_hdr(skb); struct ipv6hdr *iph = ipv6_hdr(skb);
struct udphdr _hdr, *hp = NULL; struct udphdr _hdr, *hp = NULL;
struct sock *sk; struct sock *sk = skb->sk;
struct in6_addr *daddr = NULL, *saddr = NULL; struct in6_addr *daddr = NULL, *saddr = NULL;
__be16 uninitialized_var(dport), uninitialized_var(sport); __be16 uninitialized_var(dport), uninitialized_var(sport);
int thoff = 0, uninitialized_var(tproto); int thoff = 0, uninitialized_var(tproto);
@ -291,9 +294,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
return false; return false;
} }
sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto, if (!sk)
saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY); sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
if (sk != NULL) { saddr, daddr, sport, dport,
par->in, NFT_LOOKUP_ANY);
if (sk) {
bool wildcard; bool wildcard;
bool transparent = true; bool transparent = true;
@ -309,7 +314,8 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
(sk->sk_state == TCP_TIME_WAIT && (sk->sk_state == TCP_TIME_WAIT &&
inet_twsk(sk)->tw_transparent)); inet_twsk(sk)->tw_transparent));
xt_socket_put_sk(sk); if (sk != skb->sk)
xt_socket_put_sk(sk);
if (wildcard || !transparent) if (wildcard || !transparent)
sk = NULL; sk = NULL;