diff options
| -rw-r--r-- | include/net/netfilter/nf_tproxy_core.h | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h index 1027d7f901a0..cd85b3bc8327 100644 --- a/include/net/netfilter/nf_tproxy_core.h +++ b/include/net/netfilter/nf_tproxy_core.h | |||
| @@ -5,7 +5,8 @@ | |||
| 5 | #include <linux/in.h> | 5 | #include <linux/in.h> |
| 6 | #include <linux/skbuff.h> | 6 | #include <linux/skbuff.h> |
| 7 | #include <net/sock.h> | 7 | #include <net/sock.h> |
| 8 | #include <net/inet_sock.h> | 8 | #include <net/inet_hashtables.h> |
| 9 | #include <net/inet6_hashtables.h> | ||
| 9 | #include <net/tcp.h> | 10 | #include <net/tcp.h> |
| 10 | 11 | ||
| 11 | #define NFT_LOOKUP_ANY 0 | 12 | #define NFT_LOOKUP_ANY 0 |
| @@ -130,6 +131,75 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, | |||
| 130 | return sk; | 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 | static inline void | 204 | static inline void |
| 135 | nf_tproxy_put_sock(struct sock *sk) | 205 | nf_tproxy_put_sock(struct sock *sk) |
