aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBalazs Scheidler <bazsi@balabit.hu>2010-10-21 06:47:34 -0400
committerPatrick McHardy <kaber@trash.net>2010-10-21 06:47:34 -0400
commit6006db84a91838813cdad8a6622a4e39efe9ea47 (patch)
tree842b0a7efaf2d826c82e04ae5552e9b94c6de858
parent106e4c26b1529e559d1aae777f11b4f8f7bafc26 (diff)
tproxy: add lookup type checks for UDP in nf_tproxy_get_sock_v4()
Also, inline this function as the lookup_type is always a literal and inlining removes branches performed at runtime. Signed-off-by: Balazs Scheidler <bazsi@balabit.hu> Signed-off-by: KOVACS Krisztian <hidden@balabit.hu> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/net/netfilter/nf_tproxy_core.h116
-rw-r--r--net/netfilter/nf_tproxy_core.c48
2 files changed, 114 insertions, 50 deletions
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index b3a8942a4e6a..1027d7f901a0 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -13,11 +13,123 @@
13#define NFT_LOOKUP_ESTABLISHED 2 13#define NFT_LOOKUP_ESTABLISHED 2
14 14
15/* look up and get a reference to a matching socket */ 15/* look up and get a reference to a matching socket */
16extern struct sock * 16
17
18/* This function is used by the 'TPROXY' target and the 'socket'
19 * match. The following lookups are supported:
20 *
21 * Explicit TProxy target rule
22 * ===========================
23 *
24 * This is used when the user wants to intercept a connection matching
25 * an explicit iptables rule. In this case the sockets are assumed
26 * matching in preference order:
27 *
28 * - match: if there's a fully established connection matching the
29 * _packet_ tuple, it is returned, assuming the redirection
30 * already took place and we process a packet belonging to an
31 * established connection
32 *
33 * - match: if there's a listening socket matching the redirection
34 * (e.g. on-port & on-ip of the connection), it is returned,
35 * regardless if it was bound to 0.0.0.0 or an explicit
36 * address. The reasoning is that if there's an explicit rule, it
37 * does not really matter if the listener is bound to an interface
38 * or to 0. The user already stated that he wants redirection
39 * (since he added the rule).
40 *
41 * "socket" match based redirection (no specific rule)
42 * ===================================================
43 *
44 * There are connections with dynamic endpoints (e.g. FTP data
45 * connection) that the user is unable to add explicit rules
46 * for. These are taken care of by a generic "socket" rule. It is
47 * assumed that the proxy application is trusted to open such
48 * connections without explicit iptables rule (except of course the
49 * generic 'socket' rule). In this case the following sockets are
50 * matched in preference order:
51 *
52 * - match: if there's a fully established connection matching the
53 * _packet_ tuple
54 *
55 * - match: if there's a non-zero bound listener (possibly with a
56 * non-local address) We don't accept zero-bound listeners, since
57 * then local services could intercept traffic going through the
58 * box.
59 *
60 * Please note that there's an overlap between what a TPROXY target
61 * and a socket match will match. Normally if you have both rules the
62 * "socket" match will be the first one, effectively all packets
63 * belonging to established connections going through that one.
64 */
65static inline struct sock *
17nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, 66nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
18 const __be32 saddr, const __be32 daddr, 67 const __be32 saddr, const __be32 daddr,
19 const __be16 sport, const __be16 dport, 68 const __be16 sport, const __be16 dport,
20 const struct net_device *in, int lookup_type); 69 const struct net_device *in, int lookup_type)
70{
71 struct sock *sk;
72
73 /* look up socket */
74 switch (protocol) {
75 case IPPROTO_TCP:
76 switch (lookup_type) {
77 case NFT_LOOKUP_ANY:
78 sk = __inet_lookup(net, &tcp_hashinfo,
79 saddr, sport, daddr, dport,
80 in->ifindex);
81 break;
82 case NFT_LOOKUP_LISTENER:
83 sk = inet_lookup_listener(net, &tcp_hashinfo,
84 daddr, dport,
85 in->ifindex);
86
87 /* NOTE: we return listeners even if bound to
88 * 0.0.0.0, those are filtered out in
89 * xt_socket, since xt_TPROXY needs 0 bound
90 * listeners too */
91
92 break;
93 case NFT_LOOKUP_ESTABLISHED:
94 sk = inet_lookup_established(net, &tcp_hashinfo,
95 saddr, sport, daddr, dport,
96 in->ifindex);
97 break;
98 default:
99 WARN_ON(1);
100 sk = NULL;
101 break;
102 }
103 break;
104 case IPPROTO_UDP:
105 sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
106 in->ifindex);
107 if (sk && lookup_type != NFT_LOOKUP_ANY) {
108 int connected = (sk->sk_state == TCP_ESTABLISHED);
109 int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);
110
111 /* NOTE: we return listeners even if bound to
112 * 0.0.0.0, those are filtered out in
113 * xt_socket, since xt_TPROXY needs 0 bound
114 * listeners too */
115 if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
116 (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
117 sock_put(sk);
118 sk = NULL;
119 }
120 }
121 break;
122 default:
123 WARN_ON(1);
124 sk = NULL;
125 }
126
127 pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
128 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
129
130 return sk;
131}
132
21 133
22static inline void 134static inline void
23nf_tproxy_put_sock(struct sock *sk) 135nf_tproxy_put_sock(struct sock *sk)
diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
index 8589e5e08115..db655638d76d 100644
--- a/net/netfilter/nf_tproxy_core.c
+++ b/net/netfilter/nf_tproxy_core.c
@@ -18,54 +18,6 @@
18#include <net/udp.h> 18#include <net/udp.h>
19#include <net/netfilter/nf_tproxy_core.h> 19#include <net/netfilter/nf_tproxy_core.h>
20 20
21struct sock *
22nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
23 const __be32 saddr, const __be32 daddr,
24 const __be16 sport, const __be16 dport,
25 const struct net_device *in, int lookup_type)
26{
27 struct sock *sk;
28
29 /* look up socket */
30 switch (protocol) {
31 case IPPROTO_TCP:
32 switch (lookup_type) {
33 case NFT_LOOKUP_ANY:
34 sk = __inet_lookup(net, &tcp_hashinfo,
35 saddr, sport, daddr, dport,
36 in->ifindex);
37 break;
38 case NFT_LOOKUP_LISTENER:
39 sk = inet_lookup_listener(net, &tcp_hashinfo,
40 daddr, dport,
41 in->ifindex);
42 break;
43 case NFT_LOOKUP_ESTABLISHED:
44 sk = inet_lookup_established(net, &tcp_hashinfo,
45 saddr, sport, daddr, dport,
46 in->ifindex);
47 break;
48 default:
49 WARN_ON(1);
50 sk = NULL;
51 break;
52 }
53 break;
54 case IPPROTO_UDP:
55 sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
56 in->ifindex);
57 break;
58 default:
59 WARN_ON(1);
60 sk = NULL;
61 }
62
63 pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
64 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
65
66 return sk;
67}
68EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
69 21
70static void 22static void
71nf_tproxy_destructor(struct sk_buff *skb) 23nf_tproxy_destructor(struct sk_buff *skb)