|
5 | 5 | #include <linux/in.h>
|
6 | 6 | #include <linux/skbuff.h>
|
7 | 7 | #include <net/sock.h>
|
8 |
| -#include <net/inet_sock.h> |
| 8 | +#include <net/inet_hashtables.h> |
| 9 | +#include <net/inet6_hashtables.h> |
9 | 10 | #include <net/tcp.h>
|
10 | 11 |
|
11 | 12 | #define NFT_LOOKUP_ANY 0
|
@@ -130,6 +131,75 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
|
130 | 131 | return sk;
|
131 | 132 | }
|
132 | 133 |
|
| 134 | +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 135 | +static inline struct sock * |
| 136 | +nf_tproxy_get_sock_v6(struct net *net, const u8 protocol, |
| 137 | + const struct in6_addr *saddr, const struct in6_addr *daddr, |
| 138 | + const __be16 sport, const __be16 dport, |
| 139 | + const struct net_device *in, int lookup_type) |
| 140 | +{ |
| 141 | + struct sock *sk; |
| 142 | + |
| 143 | + /* look up socket */ |
| 144 | + switch (protocol) { |
| 145 | + case IPPROTO_TCP: |
| 146 | + switch (lookup_type) { |
| 147 | + case NFT_LOOKUP_ANY: |
| 148 | + sk = inet6_lookup(net, &tcp_hashinfo, |
| 149 | + saddr, sport, daddr, dport, |
| 150 | + in->ifindex); |
| 151 | + break; |
| 152 | + case NFT_LOOKUP_LISTENER: |
| 153 | + sk = inet6_lookup_listener(net, &tcp_hashinfo, |
| 154 | + daddr, ntohs(dport), |
| 155 | + in->ifindex); |
| 156 | + |
| 157 | + /* NOTE: we return listeners even if bound to |
| 158 | + * 0.0.0.0, those are filtered out in |
| 159 | + * xt_socket, since xt_TPROXY needs 0 bound |
| 160 | + * listeners too */ |
| 161 | + |
| 162 | + break; |
| 163 | + case NFT_LOOKUP_ESTABLISHED: |
| 164 | + sk = __inet6_lookup_established(net, &tcp_hashinfo, |
| 165 | + saddr, sport, daddr, ntohs(dport), |
| 166 | + in->ifindex); |
| 167 | + break; |
| 168 | + default: |
| 169 | + WARN_ON(1); |
| 170 | + sk = NULL; |
| 171 | + break; |
| 172 | + } |
| 173 | + break; |
| 174 | + case IPPROTO_UDP: |
| 175 | + sk = udp6_lib_lookup(net, saddr, sport, daddr, dport, |
| 176 | + in->ifindex); |
| 177 | + if (sk && lookup_type != NFT_LOOKUP_ANY) { |
| 178 | + int connected = (sk->sk_state == TCP_ESTABLISHED); |
| 179 | + int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr); |
| 180 | + |
| 181 | + /* NOTE: we return listeners even if bound to |
| 182 | + * 0.0.0.0, those are filtered out in |
| 183 | + * xt_socket, since xt_TPROXY needs 0 bound |
| 184 | + * listeners too */ |
| 185 | + if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) || |
| 186 | + (lookup_type == NFT_LOOKUP_LISTENER && connected)) { |
| 187 | + sock_put(sk); |
| 188 | + sk = NULL; |
| 189 | + } |
| 190 | + } |
| 191 | + break; |
| 192 | + default: |
| 193 | + WARN_ON(1); |
| 194 | + sk = NULL; |
| 195 | + } |
| 196 | + |
| 197 | + pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n", |
| 198 | + protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk); |
| 199 | + |
| 200 | + return sk; |
| 201 | +} |
| 202 | +#endif |
133 | 203 |
|
134 | 204 | static inline void
|
135 | 205 | nf_tproxy_put_sock(struct sock *sk)
|
|
0 commit comments