Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 215498
b: refs/heads/master
c: 5bc9068
h: refs/heads/master
v: v3
  • Loading branch information
Julian Anastasov authored and Simon Horman committed Oct 21, 2010
1 parent ab135df commit cb278b0
Show file tree
Hide file tree
Showing 26 changed files with 193 additions and 980 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cc6eb433856983e91071469c4ce57accb6947ccb
refs/heads/master: 5bc9068e9d962ca6b8bec3f0eb6f60ab4dee1d04
4 changes: 0 additions & 4 deletions trunk/include/linux/in6.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,6 @@ struct in6_flowlabel_req {
/* RFC5082: Generalized Ttl Security Mechanism */
#define IPV6_MINHOPCOUNT 73

#define IPV6_ORIGDSTADDR 74
#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
#define IPV6_TRANSPARENT 75

/*
* Multicast Routing:
* see include/linux/mroute6.h.
Expand Down
4 changes: 1 addition & 3 deletions trunk/include/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,7 @@ struct ipv6_pinfo {
odstopts:1,
rxflow:1,
rxtclass:1,
rxpmtu:1,
rxorigdstaddr:1;
/* 2 bits hole */
rxpmtu:1;
} bits;
__u16 all;
} rxopt;
Expand Down
13 changes: 3 additions & 10 deletions trunk/include/linux/netfilter/xt_TPROXY.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef _XT_TPROXY_H
#define _XT_TPROXY_H
#ifndef _XT_TPROXY_H_target
#define _XT_TPROXY_H_target

/* TPROXY target is capable of marking the packet to perform
* redirection. We can get rid of that whenever we get support for
Expand All @@ -11,11 +11,4 @@ struct xt_tproxy_target_info {
__be16 lport;
};

struct xt_tproxy_target_info_v1 {
u_int32_t mark_mask;
u_int32_t mark_value;
union nf_inet_addr laddr;
__be16 lport;
};

#endif /* _XT_TPROXY_H */
#endif /* _XT_TPROXY_H_target */
2 changes: 1 addition & 1 deletion trunk/include/net/inet_hashtables.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
}

/* Caller must disable local BH processing. */
extern int __inet_inherit_port(struct sock *sk, struct sock *child);
extern void __inet_inherit_port(struct sock *sk, struct sock *child);

extern void inet_put_port(struct sock *sk);

Expand Down
6 changes: 0 additions & 6 deletions trunk/include/net/netfilter/ipv6/nf_defrag_ipv6.h

This file was deleted.

192 changes: 3 additions & 189 deletions trunk/include/net/netfilter/nf_tproxy_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,201 +5,15 @@
#include <linux/in.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/inet_hashtables.h>
#include <net/inet6_hashtables.h>
#include <net/inet_sock.h>
#include <net/tcp.h>

#define NFT_LOOKUP_ANY 0
#define NFT_LOOKUP_LISTENER 1
#define NFT_LOOKUP_ESTABLISHED 2

/* look up and get a reference to a matching socket */


/* This function is used by the 'TPROXY' target and the 'socket'
* match. The following lookups are supported:
*
* Explicit TProxy target rule
* ===========================
*
* This is used when the user wants to intercept a connection matching
* an explicit iptables rule. In this case the sockets are assumed
* matching in preference order:
*
* - match: if there's a fully established connection matching the
* _packet_ tuple, it is returned, assuming the redirection
* already took place and we process a packet belonging to an
* established connection
*
* - match: if there's a listening socket matching the redirection
* (e.g. on-port & on-ip of the connection), it is returned,
* regardless if it was bound to 0.0.0.0 or an explicit
* address. The reasoning is that if there's an explicit rule, it
* does not really matter if the listener is bound to an interface
* or to 0. The user already stated that he wants redirection
* (since he added the rule).
*
* "socket" match based redirection (no specific rule)
* ===================================================
*
* There are connections with dynamic endpoints (e.g. FTP data
* connection) that the user is unable to add explicit rules
* for. These are taken care of by a generic "socket" rule. It is
* assumed that the proxy application is trusted to open such
* connections without explicit iptables rule (except of course the
* generic 'socket' rule). In this case the following sockets are
* matched in preference order:
*
* - match: if there's a fully established connection matching the
* _packet_ tuple
*
* - match: if there's a non-zero bound listener (possibly with a
* non-local address) We don't accept zero-bound listeners, since
* then local services could intercept traffic going through the
* box.
*
* Please note that there's an overlap between what a TPROXY target
* and a socket match will match. Normally if you have both rules the
* "socket" match will be the first one, effectively all packets
* belonging to established connections going through that one.
*/
static inline struct sock *
extern struct sock *
nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
const __be32 saddr, const __be32 daddr,
const __be16 sport, const __be16 dport,
const struct net_device *in, int lookup_type)
{
struct sock *sk;

/* look up socket */
switch (protocol) {
case IPPROTO_TCP:
switch (lookup_type) {
case NFT_LOOKUP_ANY:
sk = __inet_lookup(net, &tcp_hashinfo,
saddr, sport, daddr, dport,
in->ifindex);
break;
case NFT_LOOKUP_LISTENER:
sk = inet_lookup_listener(net, &tcp_hashinfo,
daddr, dport,
in->ifindex);

/* NOTE: we return listeners even if bound to
* 0.0.0.0, those are filtered out in
* xt_socket, since xt_TPROXY needs 0 bound
* listeners too */

break;
case NFT_LOOKUP_ESTABLISHED:
sk = inet_lookup_established(net, &tcp_hashinfo,
saddr, sport, daddr, dport,
in->ifindex);
break;
default:
WARN_ON(1);
sk = NULL;
break;
}
break;
case IPPROTO_UDP:
sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
in->ifindex);
if (sk && lookup_type != NFT_LOOKUP_ANY) {
int connected = (sk->sk_state == TCP_ESTABLISHED);
int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);

/* NOTE: we return listeners even if bound to
* 0.0.0.0, those are filtered out in
* xt_socket, since xt_TPROXY needs 0 bound
* listeners too */
if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
(lookup_type == NFT_LOOKUP_LISTENER && connected)) {
sock_put(sk);
sk = NULL;
}
}
break;
default:
WARN_ON(1);
sk = NULL;
}

pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);

return sk;
}

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static inline struct sock *
nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
const struct in6_addr *saddr, const struct in6_addr *daddr,
const __be16 sport, const __be16 dport,
const struct net_device *in, int lookup_type)
{
struct sock *sk;

/* look up socket */
switch (protocol) {
case IPPROTO_TCP:
switch (lookup_type) {
case NFT_LOOKUP_ANY:
sk = inet6_lookup(net, &tcp_hashinfo,
saddr, sport, daddr, dport,
in->ifindex);
break;
case NFT_LOOKUP_LISTENER:
sk = inet6_lookup_listener(net, &tcp_hashinfo,
daddr, ntohs(dport),
in->ifindex);

/* NOTE: we return listeners even if bound to
* 0.0.0.0, those are filtered out in
* xt_socket, since xt_TPROXY needs 0 bound
* listeners too */

break;
case NFT_LOOKUP_ESTABLISHED:
sk = __inet6_lookup_established(net, &tcp_hashinfo,
saddr, sport, daddr, ntohs(dport),
in->ifindex);
break;
default:
WARN_ON(1);
sk = NULL;
break;
}
break;
case IPPROTO_UDP:
sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
in->ifindex);
if (sk && lookup_type != NFT_LOOKUP_ANY) {
int connected = (sk->sk_state == TCP_ESTABLISHED);
int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr);

/* NOTE: we return listeners even if bound to
* 0.0.0.0, those are filtered out in
* xt_socket, since xt_TPROXY needs 0 bound
* listeners too */
if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
(lookup_type == NFT_LOOKUP_LISTENER && connected)) {
sock_put(sk);
sk = NULL;
}
}
break;
default:
WARN_ON(1);
sk = NULL;
}

pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);

return sk;
}
#endif
const struct net_device *in, bool listening);

static inline void
nf_tproxy_put_sock(struct sock *sk)
Expand Down
3 changes: 0 additions & 3 deletions trunk/include/net/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,6 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport,
int dif);
extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
int dif);

/*
* SNMP statistics for UDP and UDP-Lite
Expand Down
10 changes: 3 additions & 7 deletions trunk/net/dccp/ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,

newsk = dccp_create_openreq_child(sk, req, skb);
if (newsk == NULL)
goto exit_nonewsk;
goto exit;

sk_setup_caps(newsk, dst);

Expand All @@ -409,20 +409,16 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,

dccp_sync_mss(newsk, dst_mtu(dst));

if (__inet_inherit_port(sk, newsk) < 0) {
sock_put(newsk);
goto exit;
}
__inet_hash_nolisten(newsk, NULL);
__inet_inherit_port(sk, newsk);

return newsk;

exit_overflow:
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
exit_nonewsk:
dst_release(dst);
exit:
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
dst_release(dst);
return NULL;
}

Expand Down
10 changes: 3 additions & 7 deletions trunk/net/dccp/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,

newsk = dccp_create_openreq_child(sk, req, skb);
if (newsk == NULL)
goto out_nonewsk;
goto out;

/*
* No need to charge this sock to the relevant IPv6 refcnt debug socks
Expand Down Expand Up @@ -632,22 +632,18 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
newinet->inet_rcv_saddr = LOOPBACK4_IPV6;

if (__inet_inherit_port(sk, newsk) < 0) {
sock_put(newsk);
goto out;
}
__inet6_hash(newsk, NULL);
__inet_inherit_port(sk, newsk);

return newsk;

out_overflow:
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
out_nonewsk:
dst_release(dst);
out:
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
if (opt != NULL && opt != np->opt)
sock_kfree_s(sk, opt, opt->tot_len);
dst_release(dst);
return NULL;
}

Expand Down
28 changes: 2 additions & 26 deletions trunk/net/ipv4/inet_hashtables.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,43 +101,19 @@ void inet_put_port(struct sock *sk)
}
EXPORT_SYMBOL(inet_put_port);

int __inet_inherit_port(struct sock *sk, struct sock *child)
void __inet_inherit_port(struct sock *sk, struct sock *child)
{
struct inet_hashinfo *table = sk->sk_prot->h.hashinfo;
unsigned short port = inet_sk(child)->inet_num;
const int bhash = inet_bhashfn(sock_net(sk), port,
const int bhash = inet_bhashfn(sock_net(sk), inet_sk(child)->inet_num,
table->bhash_size);
struct inet_bind_hashbucket *head = &table->bhash[bhash];
struct inet_bind_bucket *tb;

spin_lock(&head->lock);
tb = inet_csk(sk)->icsk_bind_hash;
if (tb->port != port) {
/* NOTE: using tproxy and redirecting skbs to a proxy
* on a different listener port breaks the assumption
* that the listener socket's icsk_bind_hash is the same
* as that of the child socket. We have to look up or
* create a new bind bucket for the child here. */
struct hlist_node *node;
inet_bind_bucket_for_each(tb, node, &head->chain) {
if (net_eq(ib_net(tb), sock_net(sk)) &&
tb->port == port)
break;
}
if (!node) {
tb = inet_bind_bucket_create(table->bind_bucket_cachep,
sock_net(sk), head, port);
if (!tb) {
spin_unlock(&head->lock);
return -ENOMEM;
}
}
}
sk_add_bind_node(child, &tb->owners);
inet_csk(child)->icsk_bind_hash = tb;
spin_unlock(&head->lock);

return 0;
}
EXPORT_SYMBOL_GPL(__inet_inherit_port);

Expand Down
Loading

0 comments on commit cb278b0

Please sign in to comment.