Blame view
net/netfilter/ipvs/ip_vs_xmit.c
35.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * ip_vs_xmit.c: various packet transmitters for IPVS * |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 7 8 9 10 11 12 13 |
* Authors: Wensong Zhang <wensong@linuxvirtualserver.org> * Julian Anastasov <ja@ssi.bg> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Changes: * |
cb59155f2 ipvs: changes for... |
14 15 16 17 18 19 |
* Description of forwarding methods: * - all transmitters are called from LOCAL_IN (remote clients) and * LOCAL_OUT (local clients) but for ICMP can be called from FORWARD * - not all connections have destination server, for example, * connections in backup server when fwmark is used * - bypass connections use daddr from packet |
026ace060 ipvs: optimize ds... |
20 21 |
* - we can use dst without ref while sending in RCU section, we use * ref when returning NF_ACCEPT for NAT-ed packet via loopback |
cb59155f2 ipvs: changes for... |
22 23 24 25 |
* LOCAL_OUT rules: * - skb->dev is NULL, skb->protocol is not set (both are set in POST_ROUTING) * - skb->pkt_type is not set yet * - the only place where we can see skb->sk != NULL |
1da177e4c Linux-2.6.12-rc2 |
26 |
*/ |
9aada7ac0 IPVS: use pr_fmt |
27 28 |
#define KMSG_COMPONENT "IPVS" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
1da177e4c Linux-2.6.12-rc2 |
29 |
#include <linux/kernel.h> |
5a0e3ad6a include cleanup: ... |
30 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
31 |
#include <linux/tcp.h> /* for tcphdr */ |
c439cb2e4 [IPV4]: Add ip_lo... |
32 |
#include <net/ip.h> |
1da177e4c Linux-2.6.12-rc2 |
33 34 35 36 |
#include <net/tcp.h> /* for csum_tcpudp_magic */ #include <net/udp.h> #include <net/icmp.h> /* for icmp_send */ #include <net/route.h> /* for ip_route_output */ |
38cdcc9a0 IPVS: Add IPv6 su... |
37 38 |
#include <net/ipv6.h> #include <net/ip6_route.h> |
ea1d5d775 ipvs: properly de... |
39 |
#include <net/ip_tunnels.h> |
714f095f7 ipvs: IPv6 tunnel... |
40 |
#include <net/addrconf.h> |
38cdcc9a0 IPVS: Add IPv6 su... |
41 |
#include <linux/icmpv6.h> |
1da177e4c Linux-2.6.12-rc2 |
42 43 44 45 |
#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <net/ip_vs.h> |
17a8f8e37 ipvs: use enum to... |
46 47 48 49 50 51 |
enum { IP_VS_RT_MODE_LOCAL = 1, /* Allow local dest */ IP_VS_RT_MODE_NON_LOCAL = 2, /* Allow non-local dest */ IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to * local */ |
f2edb9f77 ipvs: implement p... |
52 |
IP_VS_RT_MODE_CONNECT = 8, /* Always bind route to saddr */ |
ad4d3ef8b ipvs: fix ARP res... |
53 |
IP_VS_RT_MODE_KNOWN_NH = 16,/* Route via remote addr */ |
4115ded13 ipvs: consolidate... |
54 |
IP_VS_RT_MODE_TUNNEL = 32,/* Tunnel mode */ |
17a8f8e37 ipvs: use enum to... |
55 |
}; |
1da177e4c Linux-2.6.12-rc2 |
56 |
|
026ace060 ipvs: optimize ds... |
57 58 59 60 61 62 63 64 65 |
static inline struct ip_vs_dest_dst *ip_vs_dest_dst_alloc(void) { return kmalloc(sizeof(struct ip_vs_dest_dst), GFP_ATOMIC); } static inline void ip_vs_dest_dst_free(struct ip_vs_dest_dst *dest_dst) { kfree(dest_dst); } |
1da177e4c Linux-2.6.12-rc2 |
66 67 68 69 |
/* * Destination cache to speed up outgoing route lookup */ static inline void |
026ace060 ipvs: optimize ds... |
70 71 |
__ip_vs_dst_set(struct ip_vs_dest *dest, struct ip_vs_dest_dst *dest_dst, struct dst_entry *dst, u32 dst_cookie) |
1da177e4c Linux-2.6.12-rc2 |
72 |
{ |
026ace060 ipvs: optimize ds... |
73 74 75 76 77 78 79 80 81 82 |
struct ip_vs_dest_dst *old; old = rcu_dereference_protected(dest->dest_dst, lockdep_is_held(&dest->dst_lock)); if (dest_dst) { dest_dst->dst_cache = dst; dest_dst->dst_cookie = dst_cookie; } rcu_assign_pointer(dest->dest_dst, dest_dst); |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
026ace060 ipvs: optimize ds... |
84 85 |
if (old) call_rcu(&old->rcu_head, ip_vs_dest_dst_rcu_free); |
1da177e4c Linux-2.6.12-rc2 |
86 |
} |
026ace060 ipvs: optimize ds... |
87 |
static inline struct ip_vs_dest_dst * |
c90558dae ipvs: avoid routi... |
88 |
__ip_vs_dst_check(struct ip_vs_dest *dest) |
1da177e4c Linux-2.6.12-rc2 |
89 |
{ |
026ace060 ipvs: optimize ds... |
90 91 |
struct ip_vs_dest_dst *dest_dst = rcu_dereference(dest->dest_dst); struct dst_entry *dst; |
1da177e4c Linux-2.6.12-rc2 |
92 |
|
026ace060 ipvs: optimize ds... |
93 |
if (!dest_dst) |
1da177e4c Linux-2.6.12-rc2 |
94 |
return NULL; |
026ace060 ipvs: optimize ds... |
95 96 97 |
dst = dest_dst->dst_cache; if (dst->obsolete && dst->ops->check(dst, dest_dst->dst_cookie) == NULL) |
1da177e4c Linux-2.6.12-rc2 |
98 |
return NULL; |
026ace060 ipvs: optimize ds... |
99 |
return dest_dst; |
1da177e4c Linux-2.6.12-rc2 |
100 |
} |
590e3f79a ipvs: IPv6 MTU ch... |
101 102 103 |
static inline bool __mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu) { |
4cdd34084 netfilter: nf_con... |
104 105 106 107 108 109 110 111 |
if (IP6CB(skb)->frag_max_size) { /* frag_max_size tell us that, this packet have been * defragmented by netfilter IPv6 conntrack module. */ if (IP6CB(skb)->frag_max_size > mtu) return true; /* largest fragment violate MTU */ } else if (skb->len > mtu && !skb_is_gso(skb)) { |
590e3f79a ipvs: IPv6 MTU ch... |
112 113 114 115 |
return true; /* Packet size violate MTU size */ } return false; } |
f2edb9f77 ipvs: implement p... |
116 117 |
/* Get route to daddr, update *saddr, optionally bind route to saddr */ static struct rtable *do_output_route4(struct net *net, __be32 daddr, |
c90558dae ipvs: avoid routi... |
118 |
int rt_mode, __be32 *saddr) |
f2edb9f77 ipvs: implement p... |
119 120 121 122 123 124 125 |
{ struct flowi4 fl4; struct rtable *rt; int loop = 0; memset(&fl4, 0, sizeof(fl4)); fl4.daddr = daddr; |
ad4d3ef8b ipvs: fix ARP res... |
126 127 |
fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? FLOWI_FLAG_KNOWN_NH : 0; |
f2edb9f77 ipvs: implement p... |
128 129 130 131 132 133 134 135 |
retry: rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { /* Invalid saddr ? */ if (PTR_ERR(rt) == -EINVAL && *saddr && rt_mode & IP_VS_RT_MODE_CONNECT && !loop) { *saddr = 0; |
c90558dae ipvs: avoid routi... |
136 |
flowi4_update_output(&fl4, 0, 0, daddr, 0); |
f2edb9f77 ipvs: implement p... |
137 138 139 140 141 142 143 144 |
goto retry; } IP_VS_DBG_RL("ip_route_output error, dest: %pI4 ", &daddr); return NULL; } else if (!*saddr && rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) { ip_rt_put(rt); *saddr = fl4.saddr; |
c90558dae ipvs: avoid routi... |
145 |
flowi4_update_output(&fl4, 0, 0, daddr, fl4.saddr); |
f2edb9f77 ipvs: implement p... |
146 147 148 149 150 151 |
loop++; goto retry; } *saddr = fl4.saddr; return rt; } |
4a4739d56 ipvs: Pull out cr... |
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
#ifdef CONFIG_IP_VS_IPV6 static inline int __ip_vs_is_local_route6(struct rt6_info *rt) { return rt->dst.dev && rt->dst.dev->flags & IFF_LOOPBACK; } #endif static inline bool crosses_local_route_boundary(int skb_af, struct sk_buff *skb, int rt_mode, bool new_rt_is_local) { bool rt_mode_allow_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL); bool rt_mode_allow_non_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL); bool rt_mode_allow_redirect = !!(rt_mode & IP_VS_RT_MODE_RDR); bool source_is_loopback; bool old_rt_is_local; #ifdef CONFIG_IP_VS_IPV6 if (skb_af == AF_INET6) { int addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); source_is_loopback = (!skb->dev || skb->dev->flags & IFF_LOOPBACK) && (addr_type & IPV6_ADDR_LOOPBACK); old_rt_is_local = __ip_vs_is_local_route6( (struct rt6_info *)skb_dst(skb)); } else #endif { source_is_loopback = ipv4_is_loopback(ip_hdr(skb)->saddr); old_rt_is_local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; } if (unlikely(new_rt_is_local)) { if (!rt_mode_allow_local) return true; if (!rt_mode_allow_redirect && !old_rt_is_local) return true; } else { if (!rt_mode_allow_non_local) return true; if (source_is_loopback) return true; } return false; } |
919aa0b2b ipvs: Pull out up... |
198 199 200 201 |
static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu) { struct sock *sk = skb->sk; struct rtable *ort = skb_rtable(skb); |
a8399231f netfilter: use sk... |
202 |
if (!skb->dev && sk && sk_fullsock(sk)) |
919aa0b2b ipvs: Pull out up... |
203 204 |
ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu); } |
20868a40d ipvs: Pass ipvs i... |
205 206 |
static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af, int rt_mode, |
c63e4de2b ipvs: Add generic... |
207 208 209 210 211 |
struct ip_vs_iphdr *ipvsh, struct sk_buff *skb, int mtu) { #ifdef CONFIG_IP_VS_IPV6 if (skb_af == AF_INET6) { |
20868a40d ipvs: Pass ipvs i... |
212 |
struct net *net = ipvs->net; |
c63e4de2b ipvs: Add generic... |
213 214 215 216 217 |
if (unlikely(__mtu_check_toobig_v6(skb, mtu))) { if (!skb->dev) skb->dev = net->loopback_dev; /* only send ICMP too big on first fragment */ |
89621f31d ipvs: ensure that... |
218 |
if (!ipvsh->fragoffs && !ip_vs_iph_icmp(ipvsh)) |
c63e4de2b ipvs: Add generic... |
219 220 221 222 223 224 225 226 227 |
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP_VS_DBG(1, "frag needed for %pI6c ", &ipv6_hdr(skb)->saddr); return false; } } else #endif { |
c63e4de2b ipvs: Add generic... |
228 229 230 231 232 233 234 |
/* If we're going to tunnel the packet and pmtu discovery * is disabled, we'll just fragment it anyway */ if ((rt_mode & IP_VS_RT_MODE_TUNNEL) && !sysctl_pmtu_disc(ipvs)) return true; if (unlikely(ip_hdr(skb)->frag_off & htons(IP_DF) && |
89621f31d ipvs: ensure that... |
235 236 |
skb->len > mtu && !skb_is_gso(skb) && !ip_vs_iph_icmp(ipvsh))) { |
c63e4de2b ipvs: Add generic... |
237 238 239 240 241 242 243 244 245 246 247 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); IP_VS_DBG(1, "frag needed for %pI4 ", &ip_hdr(skb)->saddr); return false; } } return true; } |
17a8f8e37 ipvs: use enum to... |
248 |
/* Get route to destination or remote server */ |
4115ded13 ipvs: consolidate... |
249 |
static int |
ecfe87b88 ipvs: Pass ipvs i... |
250 251 |
__ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, |
c63e4de2b ipvs: Add generic... |
252 253 |
__be32 daddr, int rt_mode, __be32 *ret_saddr, struct ip_vs_iphdr *ipvsh) |
1da177e4c Linux-2.6.12-rc2 |
254 |
{ |
ecfe87b88 ipvs: Pass ipvs i... |
255 |
struct net *net = ipvs->net; |
026ace060 ipvs: optimize ds... |
256 |
struct ip_vs_dest_dst *dest_dst; |
1da177e4c Linux-2.6.12-rc2 |
257 |
struct rtable *rt; /* Route to the other host */ |
4115ded13 ipvs: consolidate... |
258 |
int mtu; |
026ace060 ipvs: optimize ds... |
259 |
int local, noref = 1; |
1da177e4c Linux-2.6.12-rc2 |
260 261 |
if (dest) { |
026ace060 ipvs: optimize ds... |
262 263 264 265 266 |
dest_dst = __ip_vs_dst_check(dest); if (likely(dest_dst)) rt = (struct rtable *) dest_dst->dst_cache; else { dest_dst = ip_vs_dest_dst_alloc(); |
ac69269a4 ipvs: do not disa... |
267 |
spin_lock_bh(&dest->dst_lock); |
026ace060 ipvs: optimize ds... |
268 269 |
if (!dest_dst) { __ip_vs_dst_set(dest, NULL, NULL, 0); |
ac69269a4 ipvs: do not disa... |
270 |
spin_unlock_bh(&dest->dst_lock); |
026ace060 ipvs: optimize ds... |
271 272 |
goto err_unreach; } |
c90558dae ipvs: avoid routi... |
273 |
rt = do_output_route4(net, dest->addr.ip, rt_mode, |
026ace060 ipvs: optimize ds... |
274 |
&dest_dst->dst_saddr.ip); |
f2edb9f77 ipvs: implement p... |
275 |
if (!rt) { |
026ace060 ipvs: optimize ds... |
276 |
__ip_vs_dst_set(dest, NULL, NULL, 0); |
ac69269a4 ipvs: do not disa... |
277 |
spin_unlock_bh(&dest->dst_lock); |
026ace060 ipvs: optimize ds... |
278 |
ip_vs_dest_dst_free(dest_dst); |
4115ded13 ipvs: consolidate... |
279 |
goto err_unreach; |
1da177e4c Linux-2.6.12-rc2 |
280 |
} |
026ace060 ipvs: optimize ds... |
281 |
__ip_vs_dst_set(dest, dest_dst, &rt->dst, 0); |
ac69269a4 ipvs: do not disa... |
282 |
spin_unlock_bh(&dest->dst_lock); |
c90558dae ipvs: avoid routi... |
283 284 |
IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d ", |
026ace060 ipvs: optimize ds... |
285 |
&dest->addr.ip, &dest_dst->dst_saddr.ip, |
c90558dae ipvs: avoid routi... |
286 |
atomic_read(&rt->dst.__refcnt)); |
1da177e4c Linux-2.6.12-rc2 |
287 |
} |
c92f5ca2e ipvs: Remove all ... |
288 |
if (ret_saddr) |
026ace060 ipvs: optimize ds... |
289 |
*ret_saddr = dest_dst->dst_saddr.ip; |
1da177e4c Linux-2.6.12-rc2 |
290 |
} else { |
f2edb9f77 ipvs: implement p... |
291 |
__be32 saddr = htonl(INADDR_ANY); |
c92f5ca2e ipvs: Remove all ... |
292 |
|
026ace060 ipvs: optimize ds... |
293 |
noref = 0; |
f2edb9f77 ipvs: implement p... |
294 295 296 297 |
/* For such unconfigured boxes avoid many route lookups * for performance reasons because we do not remember saddr */ rt_mode &= ~IP_VS_RT_MODE_CONNECT; |
c90558dae ipvs: avoid routi... |
298 |
rt = do_output_route4(net, daddr, rt_mode, &saddr); |
f2edb9f77 ipvs: implement p... |
299 |
if (!rt) |
4115ded13 ipvs: consolidate... |
300 |
goto err_unreach; |
c92f5ca2e ipvs: Remove all ... |
301 |
if (ret_saddr) |
f2edb9f77 ipvs: implement p... |
302 |
*ret_saddr = saddr; |
1da177e4c Linux-2.6.12-rc2 |
303 |
} |
4115ded13 ipvs: consolidate... |
304 |
local = (rt->rt_flags & RTCF_LOCAL) ? 1 : 0; |
4a4739d56 ipvs: Pull out cr... |
305 306 307 |
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode, local))) { IP_VS_DBG_RL("We are crossing local and non-local addresses" |
3d53666b4 ipvs: Avoid null-... |
308 309 |
" daddr=%pI4 ", &daddr); |
4115ded13 ipvs: consolidate... |
310 |
goto err_put; |
fc6047676 ipvs: changes for... |
311 |
} |
4a4739d56 ipvs: Pull out cr... |
312 313 |
if (unlikely(local)) { |
4115ded13 ipvs: consolidate... |
314 |
/* skb to local stack, preserve old route */ |
026ace060 ipvs: optimize ds... |
315 316 |
if (!noref) ip_rt_put(rt); |
4115ded13 ipvs: consolidate... |
317 |
return local; |
fc6047676 ipvs: changes for... |
318 |
} |
4115ded13 ipvs: consolidate... |
319 320 321 |
if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) { mtu = dst_mtu(&rt->dst); |
4115ded13 ipvs: consolidate... |
322 |
} else { |
4115ded13 ipvs: consolidate... |
323 324 325 326 327 328 |
mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); if (mtu < 68) { IP_VS_DBG_RL("%s(): mtu less than 68 ", __func__); goto err_put; } |
919aa0b2b ipvs: Pull out up... |
329 |
maybe_update_pmtu(skb_af, skb, mtu); |
fc6047676 ipvs: changes for... |
330 |
} |
20868a40d ipvs: Pass ipvs i... |
331 |
if (!ensure_mtu_is_adequate(ipvs, skb_af, rt_mode, ipvsh, skb, mtu)) |
4115ded13 ipvs: consolidate... |
332 |
goto err_put; |
4115ded13 ipvs: consolidate... |
333 334 |
skb_dst_drop(skb); |
026ace060 ipvs: optimize ds... |
335 336 |
if (noref) { if (!local) |
dbfc4fb7d dst: no need to t... |
337 |
skb_dst_set_noref(skb, &rt->dst); |
026ace060 ipvs: optimize ds... |
338 339 340 341 |
else skb_dst_set(skb, dst_clone(&rt->dst)); } else skb_dst_set(skb, &rt->dst); |
4115ded13 ipvs: consolidate... |
342 343 344 345 |
return local; err_put: |
026ace060 ipvs: optimize ds... |
346 347 |
if (!noref) ip_rt_put(rt); |
4115ded13 ipvs: consolidate... |
348 349 350 351 352 |
return -1; err_unreach: dst_link_failure(skb); return -1; |
1da177e4c Linux-2.6.12-rc2 |
353 |
} |
38cdcc9a0 IPVS: Add IPv6 su... |
354 |
#ifdef CONFIG_IP_VS_IPV6 |
714f095f7 ipvs: IPv6 tunnel... |
355 356 |
static struct dst_entry * __ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr, |
48e8aa6e3 ipv6: Set FLOWI_F... |
357 |
struct in6_addr *ret_saddr, int do_xfrm, int rt_mode) |
714f095f7 ipvs: IPv6 tunnel... |
358 359 |
{ struct dst_entry *dst; |
4c9483b2f ipv6: Convert to ... |
360 361 |
struct flowi6 fl6 = { .daddr = *daddr, |
714f095f7 ipvs: IPv6 tunnel... |
362 |
}; |
48e8aa6e3 ipv6: Set FLOWI_F... |
363 364 |
if (rt_mode & IP_VS_RT_MODE_KNOWN_NH) fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH; |
4c9483b2f ipv6: Convert to ... |
365 |
dst = ip6_route_output(net, NULL, &fl6); |
714f095f7 ipvs: IPv6 tunnel... |
366 367 368 369 |
if (dst->error) goto out_err; if (!ret_saddr) return dst; |
4c9483b2f ipv6: Convert to ... |
370 |
if (ipv6_addr_any(&fl6.saddr) && |
714f095f7 ipvs: IPv6 tunnel... |
371 |
ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev, |
4c9483b2f ipv6: Convert to ... |
372 |
&fl6.daddr, 0, &fl6.saddr) < 0) |
714f095f7 ipvs: IPv6 tunnel... |
373 |
goto out_err; |
452edd598 xfrm: Return dst ... |
374 |
if (do_xfrm) { |
4c9483b2f ipv6: Convert to ... |
375 |
dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
452edd598 xfrm: Return dst ... |
376 377 378 379 380 |
if (IS_ERR(dst)) { dst = NULL; goto out_err; } } |
4e3fd7a06 net: remove ipv6_... |
381 |
*ret_saddr = fl6.saddr; |
714f095f7 ipvs: IPv6 tunnel... |
382 383 384 385 386 387 388 389 |
return dst; out_err: dst_release(dst); IP_VS_DBG_RL("ip6_route_output error, dest: %pI6 ", daddr); return NULL; } |
fc6047676 ipvs: changes for... |
390 391 |
/* * Get route to destination or remote server |
fc6047676 ipvs: changes for... |
392 |
*/ |
4115ded13 ipvs: consolidate... |
393 |
static int |
f5745f8ae ipvs: Pass ipvs i... |
394 395 |
__ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, |
fc6047676 ipvs: changes for... |
396 |
struct in6_addr *daddr, struct in6_addr *ret_saddr, |
4115ded13 ipvs: consolidate... |
397 |
struct ip_vs_iphdr *ipvsh, int do_xfrm, int rt_mode) |
38cdcc9a0 IPVS: Add IPv6 su... |
398 |
{ |
f5745f8ae ipvs: Pass ipvs i... |
399 |
struct net *net = ipvs->net; |
026ace060 ipvs: optimize ds... |
400 |
struct ip_vs_dest_dst *dest_dst; |
38cdcc9a0 IPVS: Add IPv6 su... |
401 |
struct rt6_info *rt; /* Route to the other host */ |
714f095f7 ipvs: IPv6 tunnel... |
402 |
struct dst_entry *dst; |
4115ded13 ipvs: consolidate... |
403 |
int mtu; |
026ace060 ipvs: optimize ds... |
404 |
int local, noref = 1; |
38cdcc9a0 IPVS: Add IPv6 su... |
405 406 |
if (dest) { |
026ace060 ipvs: optimize ds... |
407 408 409 410 |
dest_dst = __ip_vs_dst_check(dest); if (likely(dest_dst)) rt = (struct rt6_info *) dest_dst->dst_cache; else { |
714f095f7 ipvs: IPv6 tunnel... |
411 |
u32 cookie; |
38cdcc9a0 IPVS: Add IPv6 su... |
412 |
|
026ace060 ipvs: optimize ds... |
413 |
dest_dst = ip_vs_dest_dst_alloc(); |
ac69269a4 ipvs: do not disa... |
414 |
spin_lock_bh(&dest->dst_lock); |
026ace060 ipvs: optimize ds... |
415 416 |
if (!dest_dst) { __ip_vs_dst_set(dest, NULL, NULL, 0); |
ac69269a4 ipvs: do not disa... |
417 |
spin_unlock_bh(&dest->dst_lock); |
026ace060 ipvs: optimize ds... |
418 419 |
goto err_unreach; } |
714f095f7 ipvs: IPv6 tunnel... |
420 |
dst = __ip_vs_route_output_v6(net, &dest->addr.in6, |
026ace060 ipvs: optimize ds... |
421 |
&dest_dst->dst_saddr.in6, |
48e8aa6e3 ipv6: Set FLOWI_F... |
422 |
do_xfrm, rt_mode); |
714f095f7 ipvs: IPv6 tunnel... |
423 |
if (!dst) { |
026ace060 ipvs: optimize ds... |
424 |
__ip_vs_dst_set(dest, NULL, NULL, 0); |
ac69269a4 ipvs: do not disa... |
425 |
spin_unlock_bh(&dest->dst_lock); |
026ace060 ipvs: optimize ds... |
426 |
ip_vs_dest_dst_free(dest_dst); |
4115ded13 ipvs: consolidate... |
427 |
goto err_unreach; |
38cdcc9a0 IPVS: Add IPv6 su... |
428 |
} |
714f095f7 ipvs: IPv6 tunnel... |
429 |
rt = (struct rt6_info *) dst; |
b197df4f0 ipv6: Add rt6_get... |
430 |
cookie = rt6_get_cookie(rt); |
026ace060 ipvs: optimize ds... |
431 |
__ip_vs_dst_set(dest, dest_dst, &rt->dst, cookie); |
ac69269a4 ipvs: do not disa... |
432 |
spin_unlock_bh(&dest->dst_lock); |
714f095f7 ipvs: IPv6 tunnel... |
433 434 |
IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d ", |
026ace060 ipvs: optimize ds... |
435 |
&dest->addr.in6, &dest_dst->dst_saddr.in6, |
d8d1f30b9 net-next: remove ... |
436 |
atomic_read(&rt->dst.__refcnt)); |
38cdcc9a0 IPVS: Add IPv6 su... |
437 |
} |
714f095f7 ipvs: IPv6 tunnel... |
438 |
if (ret_saddr) |
026ace060 ipvs: optimize ds... |
439 |
*ret_saddr = dest_dst->dst_saddr.in6; |
38cdcc9a0 IPVS: Add IPv6 su... |
440 |
} else { |
026ace060 ipvs: optimize ds... |
441 |
noref = 0; |
48e8aa6e3 ipv6: Set FLOWI_F... |
442 443 |
dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm, rt_mode); |
714f095f7 ipvs: IPv6 tunnel... |
444 |
if (!dst) |
4115ded13 ipvs: consolidate... |
445 |
goto err_unreach; |
714f095f7 ipvs: IPv6 tunnel... |
446 |
rt = (struct rt6_info *) dst; |
38cdcc9a0 IPVS: Add IPv6 su... |
447 |
} |
fc6047676 ipvs: changes for... |
448 |
local = __ip_vs_is_local_route6(rt); |
4a4739d56 ipvs: Pull out cr... |
449 450 451 452 |
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode, local))) { IP_VS_DBG_RL("We are crossing local and non-local addresses" |
3d53666b4 ipvs: Avoid null-... |
453 454 |
" daddr=%pI6 ", daddr); |
4115ded13 ipvs: consolidate... |
455 |
goto err_put; |
fc6047676 ipvs: changes for... |
456 |
} |
4a4739d56 ipvs: Pull out cr... |
457 458 |
if (unlikely(local)) { |
4115ded13 ipvs: consolidate... |
459 |
/* skb to local stack, preserve old route */ |
026ace060 ipvs: optimize ds... |
460 461 |
if (!noref) dst_release(&rt->dst); |
4115ded13 ipvs: consolidate... |
462 |
return local; |
fc6047676 ipvs: changes for... |
463 |
} |
4115ded13 ipvs: consolidate... |
464 465 466 467 468 |
/* MTU checking */ if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) mtu = dst_mtu(&rt->dst); else { |
4115ded13 ipvs: consolidate... |
469 470 471 472 473 474 475 |
mtu = dst_mtu(&rt->dst) - sizeof(struct ipv6hdr); if (mtu < IPV6_MIN_MTU) { IP_VS_DBG_RL("%s(): mtu less than %d ", __func__, IPV6_MIN_MTU); goto err_put; } |
919aa0b2b ipvs: Pull out up... |
476 |
maybe_update_pmtu(skb_af, skb, mtu); |
fc6047676 ipvs: changes for... |
477 |
} |
20868a40d ipvs: Pass ipvs i... |
478 |
if (!ensure_mtu_is_adequate(ipvs, skb_af, rt_mode, ipvsh, skb, mtu)) |
4115ded13 ipvs: consolidate... |
479 |
goto err_put; |
4115ded13 ipvs: consolidate... |
480 481 |
skb_dst_drop(skb); |
026ace060 ipvs: optimize ds... |
482 483 |
if (noref) { if (!local) |
dbfc4fb7d dst: no need to t... |
484 |
skb_dst_set_noref(skb, &rt->dst); |
026ace060 ipvs: optimize ds... |
485 486 487 488 |
else skb_dst_set(skb, dst_clone(&rt->dst)); } else skb_dst_set(skb, &rt->dst); |
4115ded13 ipvs: consolidate... |
489 490 491 492 |
return local; err_put: |
026ace060 ipvs: optimize ds... |
493 494 |
if (!noref) dst_release(&rt->dst); |
4115ded13 ipvs: consolidate... |
495 496 497 |
return -1; err_unreach: |
326bf17ea ipvs: fix ipv6 ro... |
498 499 500 501 502 503 |
/* The ip6_link_failure function requires the dev field to be set * in order to get the net (further for the sake of fwmark * reflection). */ if (!skb->dev) skb->dev = skb_dst(skb)->dev; |
4115ded13 ipvs: consolidate... |
504 505 |
dst_link_failure(skb); return -1; |
38cdcc9a0 IPVS: Add IPv6 su... |
506 507 |
} #endif |
1da177e4c Linux-2.6.12-rc2 |
508 |
|
b8abdf098 ipvs: convert the... |
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 |
/* return NF_ACCEPT to allow forwarding or other NF_xxx on error */ static inline int ip_vs_tunnel_xmit_prepare(struct sk_buff *skb, struct ip_vs_conn *cp) { int ret = NF_ACCEPT; skb->ipvs_property = 1; if (unlikely(cp->flags & IP_VS_CONN_F_NFCT)) ret = ip_vs_confirm_conntrack(skb); if (ret == NF_ACCEPT) { nf_reset(skb); skb_forward_csum(skb); } return ret; } |
71563f341 ipvs: skb_orphan ... |
524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
/* In the event of a remote destination, it's possible that we would have * matches against an old socket (particularly a TIME-WAIT socket). This * causes havoc down the line (ip_local_out et. al. expect regular sockets * and invalid memory accesses will happen) so simply drop the association * in this case. */ static inline void ip_vs_drop_early_demux_sk(struct sk_buff *skb) { /* If dev is set, the packet came from the LOCAL_IN callback and * not from a local TCP socket. */ if (skb->dev) skb_orphan(skb); } |
b8abdf098 ipvs: convert the... |
538 539 540 541 542 543 544 545 546 547 548 |
/* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, struct ip_vs_conn *cp, int local) { int ret = NF_STOLEN; skb->ipvs_property = 1; if (likely(!(cp->flags & IP_VS_CONN_F_NFCT))) ip_vs_notrack(skb); else ip_vs_update_conntrack(skb, cp, 1); |
71563f341 ipvs: skb_orphan ... |
549 550 551 552 553 554 555 |
/* Remove the early_demux association unless it's bound for the * exact same port and address on this host after translation. */ if (!local || cp->vport != cp->dport || !ip_vs_addr_equal(cp->af, &cp->vaddr, &cp->daddr)) ip_vs_drop_early_demux_sk(skb); |
b8abdf098 ipvs: convert the... |
556 557 |
if (!local) { skb_forward_csum(skb); |
58dbc6f26 ipvs: Store ipvs ... |
558 |
NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb, |
13206b6bf net: Pass net int... |
559 |
NULL, skb_dst(skb)->dev, dst_output); |
b8abdf098 ipvs: convert the... |
560 561 |
} else ret = NF_ACCEPT; |
71563f341 ipvs: skb_orphan ... |
562 |
|
b8abdf098 ipvs: convert the... |
563 564 565 566 567 568 569 570 571 572 573 574 575 |
return ret; } /* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb, struct ip_vs_conn *cp, int local) { int ret = NF_STOLEN; skb->ipvs_property = 1; if (likely(!(cp->flags & IP_VS_CONN_F_NFCT))) ip_vs_notrack(skb); if (!local) { |
71563f341 ipvs: skb_orphan ... |
576 |
ip_vs_drop_early_demux_sk(skb); |
b8abdf098 ipvs: convert the... |
577 |
skb_forward_csum(skb); |
58dbc6f26 ipvs: Store ipvs ... |
578 |
NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb, |
13206b6bf net: Pass net int... |
579 |
NULL, skb_dst(skb)->dev, dst_output); |
b8abdf098 ipvs: convert the... |
580 581 582 583 |
} else ret = NF_ACCEPT; return ret; } |
1da177e4c Linux-2.6.12-rc2 |
584 585 586 587 588 589 590 |
/* * NULL transmitter (do nothing except return NF_ACCEPT) */ int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
591 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
1da177e4c Linux-2.6.12-rc2 |
592 593 |
{ /* we do not touch skb and do not need pskb ptr */ |
b8abdf098 ipvs: convert the... |
594 |
return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1); |
1da177e4c Linux-2.6.12-rc2 |
595 596 597 598 599 600 601 602 603 604 |
} /* * Bypass transmitter * Let packets bypass the destination when the destination is not * available, it may be only used in transparent cache cluster. */ int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
605 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
1da177e4c Linux-2.6.12-rc2 |
606 |
{ |
eddc9ec53 [SK_BUFF]: Introd... |
607 |
struct iphdr *iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
608 609 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
610 |
rcu_read_lock(); |
ecfe87b88 ipvs: Pass ipvs i... |
611 |
if (__ip_vs_get_out_rt(cp->ipvs, cp->af, skb, NULL, iph->daddr, |
c63e4de2b ipvs: Add generic... |
612 |
IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh) < 0) |
1da177e4c Linux-2.6.12-rc2 |
613 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
614 |
|
4115ded13 ipvs: consolidate... |
615 |
ip_send_check(iph); |
1da177e4c Linux-2.6.12-rc2 |
616 617 |
/* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
618 |
skb->ignore_df = 1; |
1da177e4c Linux-2.6.12-rc2 |
619 |
|
b8abdf098 ipvs: convert the... |
620 |
ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 0); |
026ace060 ipvs: optimize ds... |
621 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
622 623 624 |
LeaveFunction(10); return NF_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
625 626 |
tx_error: kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
627 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
628 629 630 |
LeaveFunction(10); return NF_STOLEN; } |
b3cdd2a73 IPVS: Add and bin... |
631 632 633 |
#ifdef CONFIG_IP_VS_IPV6 int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, |
4115ded13 ipvs: consolidate... |
634 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
b3cdd2a73 IPVS: Add and bin... |
635 |
{ |
3481894fc ipvs: Use outer h... |
636 |
struct ipv6hdr *iph = ipv6_hdr(skb); |
b3cdd2a73 IPVS: Add and bin... |
637 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
638 |
rcu_read_lock(); |
f5745f8ae ipvs: Pass ipvs i... |
639 640 |
if (__ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, NULL, &iph->daddr, NULL, |
4115ded13 ipvs: consolidate... |
641 |
ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL) < 0) |
b3cdd2a73 IPVS: Add and bin... |
642 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
643 644 |
/* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
645 |
skb->ignore_df = 1; |
b3cdd2a73 IPVS: Add and bin... |
646 |
|
b8abdf098 ipvs: convert the... |
647 |
ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 0); |
026ace060 ipvs: optimize ds... |
648 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
649 650 651 |
LeaveFunction(10); return NF_STOLEN; |
b3cdd2a73 IPVS: Add and bin... |
652 653 |
tx_error: kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
654 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
655 656 657 658 |
LeaveFunction(10); return NF_STOLEN; } #endif |
1da177e4c Linux-2.6.12-rc2 |
659 660 661 662 663 664 665 |
/* * NAT transmitter (only for outside-to-inside nat forwarding) * Not used for related ICMP */ int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
666 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
1da177e4c Linux-2.6.12-rc2 |
667 668 |
{ struct rtable *rt; /* Route to the other host */ |
4115ded13 ipvs: consolidate... |
669 |
int local, rc, was_input; |
1da177e4c Linux-2.6.12-rc2 |
670 671 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
672 |
rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
673 674 |
/* check if it is a connection of no-client-port */ if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) { |
014d730d5 [IPVS]: ipvs anno... |
675 |
__be16 _pt, *p; |
4115ded13 ipvs: consolidate... |
676 677 |
p = skb_header_pointer(skb, ipvsh->len, sizeof(_pt), &_pt); |
1da177e4c Linux-2.6.12-rc2 |
678 679 680 681 682 683 |
if (p == NULL) goto tx_error; ip_vs_conn_fill_cport(cp, *p); IP_VS_DBG(10, "filled cport=%d ", ntohs(*p)); } |
4115ded13 ipvs: consolidate... |
684 |
was_input = rt_is_input_route(skb_rtable(skb)); |
ecfe87b88 ipvs: Pass ipvs i... |
685 |
local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, |
4115ded13 ipvs: consolidate... |
686 687 |
IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | |
c63e4de2b ipvs: Add generic... |
688 |
IP_VS_RT_MODE_RDR, NULL, ipvsh); |
4115ded13 ipvs: consolidate... |
689 690 691 |
if (local < 0) goto tx_error; rt = skb_rtable(skb); |
fc6047676 ipvs: changes for... |
692 693 694 695 |
/* * Avoid duplicate tuple in reply direction for NAT traffic * to local address when connection is sync-ed */ |
c0cd11566 net:netfilter: us... |
696 |
#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
fc6047676 ipvs: changes for... |
697 698 |
if (cp->flags & IP_VS_CONN_F_SYNC && local) { enum ip_conntrack_info ctinfo; |
05b4b065a ipvs: remove sill... |
699 |
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
fc6047676 ipvs: changes for... |
700 701 |
if (ct && !nf_ct_is_untracked(ct)) { |
b0e010c52 ipvs: replace ip_... |
702 |
IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, ipvsh->off, |
0d79641a9 ipvs: provide add... |
703 |
"ip_vs_nat_xmit(): " |
fc6047676 ipvs: changes for... |
704 |
"stopping DNAT to local address"); |
4115ded13 ipvs: consolidate... |
705 |
goto tx_error; |
fc6047676 ipvs: changes for... |
706 707 708 709 710 |
} } #endif /* From world but DNAT to loopback address? */ |
4115ded13 ipvs: consolidate... |
711 |
if (local && ipv4_is_loopback(cp->daddr.ip) && was_input) { |
b0e010c52 ipvs: replace ip_... |
712 713 714 |
IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, ipvsh->off, "ip_vs_nat_xmit(): stopping DNAT to loopback " "address"); |
4115ded13 ipvs: consolidate... |
715 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
716 717 718 |
} /* copy-on-write the packet before mangling it */ |
af1e1cf07 [IPVS]: Replace l... |
719 |
if (!skb_make_writable(skb, sizeof(struct iphdr))) |
4115ded13 ipvs: consolidate... |
720 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
721 |
|
d8d1f30b9 net-next: remove ... |
722 |
if (skb_cow(skb, rt->dst.dev->hard_header_len)) |
4115ded13 ipvs: consolidate... |
723 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
724 |
|
1da177e4c Linux-2.6.12-rc2 |
725 |
/* mangle the packet */ |
d4383f04d ipvs: API change ... |
726 |
if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, ipvsh)) |
4115ded13 ipvs: consolidate... |
727 |
goto tx_error; |
e7ade46a5 IPVS: Change IPVS... |
728 |
ip_hdr(skb)->daddr = cp->daddr.ip; |
eddc9ec53 [SK_BUFF]: Introd... |
729 |
ip_send_check(ip_hdr(skb)); |
1da177e4c Linux-2.6.12-rc2 |
730 |
|
b0e010c52 ipvs: replace ip_... |
731 |
IP_VS_DBG_PKT(10, AF_INET, pp, skb, ipvsh->off, "After DNAT"); |
1da177e4c Linux-2.6.12-rc2 |
732 733 734 735 736 737 |
/* FIXME: when application helper enlarges the packet and the length is larger than the MTU of outgoing device, there will be still MTU problem. */ /* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
738 |
skb->ignore_df = 1; |
1da177e4c Linux-2.6.12-rc2 |
739 |
|
b8abdf098 ipvs: convert the... |
740 |
rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local); |
026ace060 ipvs: optimize ds... |
741 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
742 743 |
LeaveFunction(10); |
b8abdf098 ipvs: convert the... |
744 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
745 |
|
1da177e4c Linux-2.6.12-rc2 |
746 |
tx_error: |
1da177e4c Linux-2.6.12-rc2 |
747 |
kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
748 |
rcu_read_unlock(); |
f4bc17cdd ipvs: netfilter c... |
749 |
LeaveFunction(10); |
1da177e4c Linux-2.6.12-rc2 |
750 |
return NF_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
751 |
} |
b3cdd2a73 IPVS: Add and bin... |
752 753 754 |
#ifdef CONFIG_IP_VS_IPV6 int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, |
4115ded13 ipvs: consolidate... |
755 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
b3cdd2a73 IPVS: Add and bin... |
756 757 |
{ struct rt6_info *rt; /* Route to the other host */ |
b8abdf098 ipvs: convert the... |
758 |
int local, rc; |
b3cdd2a73 IPVS: Add and bin... |
759 760 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
761 |
rcu_read_lock(); |
b3cdd2a73 IPVS: Add and bin... |
762 |
/* check if it is a connection of no-client-port */ |
4115ded13 ipvs: consolidate... |
763 |
if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT && !ipvsh->fragoffs)) { |
b3cdd2a73 IPVS: Add and bin... |
764 |
__be16 _pt, *p; |
4115ded13 ipvs: consolidate... |
765 |
p = skb_header_pointer(skb, ipvsh->len, sizeof(_pt), &_pt); |
b3cdd2a73 IPVS: Add and bin... |
766 767 768 769 770 771 |
if (p == NULL) goto tx_error; ip_vs_conn_fill_cport(cp, *p); IP_VS_DBG(10, "filled cport=%d ", ntohs(*p)); } |
f5745f8ae ipvs: Pass ipvs i... |
772 773 |
local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest, &cp->daddr.in6, |
4a4739d56 ipvs: Pull out cr... |
774 |
NULL, ipvsh, 0, |
4115ded13 ipvs: consolidate... |
775 776 777 778 779 780 |
IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR); if (local < 0) goto tx_error; rt = (struct rt6_info *) skb_dst(skb); |
fc6047676 ipvs: changes for... |
781 782 783 784 |
/* * Avoid duplicate tuple in reply direction for NAT traffic * to local address when connection is sync-ed */ |
c0cd11566 net:netfilter: us... |
785 |
#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
fc6047676 ipvs: changes for... |
786 787 |
if (cp->flags & IP_VS_CONN_F_SYNC && local) { enum ip_conntrack_info ctinfo; |
05b4b065a ipvs: remove sill... |
788 |
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
fc6047676 ipvs: changes for... |
789 790 |
if (ct && !nf_ct_is_untracked(ct)) { |
b0e010c52 ipvs: replace ip_... |
791 |
IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, ipvsh->off, |
fc6047676 ipvs: changes for... |
792 793 |
"ip_vs_nat_xmit_v6(): " "stopping DNAT to local address"); |
4115ded13 ipvs: consolidate... |
794 |
goto tx_error; |
fc6047676 ipvs: changes for... |
795 796 797 798 799 800 |
} } #endif /* From world but DNAT to loopback address? */ if (local && skb->dev && !(skb->dev->flags & IFF_LOOPBACK) && |
fd0273d79 ipv6: Remove exte... |
801 |
ipv6_addr_type(&cp->daddr.in6) & IPV6_ADDR_LOOPBACK) { |
b0e010c52 ipvs: replace ip_... |
802 |
IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, ipvsh->off, |
fc6047676 ipvs: changes for... |
803 804 |
"ip_vs_nat_xmit_v6(): " "stopping DNAT to loopback address"); |
4115ded13 ipvs: consolidate... |
805 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
806 807 808 809 |
} /* copy-on-write the packet before mangling it */ if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) |
4115ded13 ipvs: consolidate... |
810 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
811 |
|
d8d1f30b9 net-next: remove ... |
812 |
if (skb_cow(skb, rt->dst.dev->hard_header_len)) |
4115ded13 ipvs: consolidate... |
813 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
814 |
|
b3cdd2a73 IPVS: Add and bin... |
815 |
/* mangle the packet */ |
4115ded13 ipvs: consolidate... |
816 |
if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, ipvsh)) |
b3cdd2a73 IPVS: Add and bin... |
817 |
goto tx_error; |
4e3fd7a06 net: remove ipv6_... |
818 |
ipv6_hdr(skb)->daddr = cp->daddr.in6; |
fc6047676 ipvs: changes for... |
819 |
|
b0e010c52 ipvs: replace ip_... |
820 |
IP_VS_DBG_PKT(10, AF_INET6, pp, skb, ipvsh->off, "After DNAT"); |
b3cdd2a73 IPVS: Add and bin... |
821 822 823 824 825 826 |
/* FIXME: when application helper enlarges the packet and the length is larger than the MTU of outgoing device, there will be still MTU problem. */ /* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
827 |
skb->ignore_df = 1; |
b3cdd2a73 IPVS: Add and bin... |
828 |
|
b8abdf098 ipvs: convert the... |
829 |
rc = ip_vs_nat_send_or_cont(NFPROTO_IPV6, skb, cp, local); |
026ace060 ipvs: optimize ds... |
830 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
831 832 |
LeaveFunction(10); |
b8abdf098 ipvs: convert the... |
833 |
return rc; |
b3cdd2a73 IPVS: Add and bin... |
834 |
|
b3cdd2a73 IPVS: Add and bin... |
835 836 837 |
tx_error: LeaveFunction(10); kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
838 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
839 |
return NF_STOLEN; |
b3cdd2a73 IPVS: Add and bin... |
840 841 |
} #endif |
8052ba292 ipvs: support ipv... |
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 |
/* When forwarding a packet, we must ensure that we've got enough headroom * for the encapsulation packet in the skb. This also gives us an * opportunity to figure out what the payload_len, dsfield, ttl, and df * values should be, so that we won't need to look at the old ip header * again */ static struct sk_buff * ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, unsigned int max_headroom, __u8 *next_protocol, __u32 *payload_len, __u8 *dsfield, __u8 *ttl, __be16 *df) { struct sk_buff *new_skb = NULL; struct iphdr *old_iph = NULL; #ifdef CONFIG_IP_VS_IPV6 struct ipv6hdr *old_ipv6h = NULL; #endif |
71563f341 ipvs: skb_orphan ... |
859 |
ip_vs_drop_early_demux_sk(skb); |
8052ba292 ipvs: support ipv... |
860 861 862 863 |
if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) { new_skb = skb_realloc_headroom(skb, max_headroom); if (!new_skb) goto error; |
50656d9df ipvs: Keep skb->s... |
864 865 |
if (skb->sk) skb_set_owner_w(new_skb, skb->sk); |
8052ba292 ipvs: support ipv... |
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
consume_skb(skb); skb = new_skb; } #ifdef CONFIG_IP_VS_IPV6 if (skb_af == AF_INET6) { old_ipv6h = ipv6_hdr(skb); *next_protocol = IPPROTO_IPV6; if (payload_len) *payload_len = ntohs(old_ipv6h->payload_len) + sizeof(*old_ipv6h); *dsfield = ipv6_get_dsfield(old_ipv6h); *ttl = old_ipv6h->hop_limit; if (df) *df = 0; } else #endif { old_iph = ip_hdr(skb); /* Copy DF, reset fragment offset and MF */ if (df) *df = (old_iph->frag_off & htons(IP_DF)); *next_protocol = IPPROTO_IPIP; /* fix old IP header checksum */ ip_send_check(old_iph); *dsfield = ipv4_get_dsfield(old_iph); *ttl = old_iph->ttl; if (payload_len) *payload_len = ntohs(old_iph->tot_len); } return skb; error: kfree_skb(skb); return ERR_PTR(-ENOMEM); } static inline int __tun_gso_type_mask(int encaps_af, int orig_af) { |
7e13318da net: define gso t... |
907 908 909 910 911 912 913 |
switch (encaps_af) { case AF_INET: return SKB_GSO_IPXIP4; case AF_INET6: return SKB_GSO_IPXIP6; default: return 0; |
8052ba292 ipvs: support ipv... |
914 |
} |
8052ba292 ipvs: support ipv... |
915 |
} |
1da177e4c Linux-2.6.12-rc2 |
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 |
/* * IP Tunneling transmitter * * This function encapsulates the packet in a new IP packet, its * destination will be set to cp->daddr. Most code of this function * is taken from ipip.c. * * It is used in VS/TUN cluster. The load balancer selects a real * server from a cluster based on a scheduling algorithm, * encapsulates the request packet and forwards it to the selected * server. For example, all real servers are configured with * "ifconfig tunl0 <Virtual IP Address> up". When the server receives * the encapsulated packet, it will decapsulate the packet, processe * the request and return the response packets directly to the client * without passing the load balancer. This can greatly increase the * scalability of virtual server. * * Used for ANY protocol */ int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
938 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
1da177e4c Linux-2.6.12-rc2 |
939 |
{ |
361c3f529 ipvs: Better deri... |
940 941 |
struct netns_ipvs *ipvs = cp->ipvs; struct net *net = ipvs->net; |
1da177e4c Linux-2.6.12-rc2 |
942 |
struct rtable *rt; /* Route to the other host */ |
c92f5ca2e ipvs: Remove all ... |
943 |
__be32 saddr; /* Source for tunnel */ |
1da177e4c Linux-2.6.12-rc2 |
944 |
struct net_device *tdev; /* Device to other host */ |
8052ba292 ipvs: support ipv... |
945 946 947 948 949 |
__u8 next_protocol = 0; __u8 dsfield = 0; __u8 ttl = 0; __be16 df = 0; __be16 *dfp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
950 |
struct iphdr *iph; /* Our new IP header */ |
c2636b4d9 [NET]: Treat the ... |
951 |
unsigned int max_headroom; /* The extra header space needed */ |
4115ded13 ipvs: consolidate... |
952 |
int ret, local; |
1da177e4c Linux-2.6.12-rc2 |
953 954 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
955 |
rcu_read_lock(); |
ecfe87b88 ipvs: Pass ipvs i... |
956 |
local = __ip_vs_get_out_rt(ipvs, cp->af, skb, cp->dest, cp->daddr.ip, |
4115ded13 ipvs: consolidate... |
957 958 959 |
IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_CONNECT | |
c63e4de2b ipvs: Add generic... |
960 |
IP_VS_RT_MODE_TUNNEL, &saddr, ipvsh); |
4115ded13 ipvs: consolidate... |
961 962 |
if (local < 0) goto tx_error; |
026ace060 ipvs: optimize ds... |
963 964 |
if (local) { rcu_read_unlock(); |
b8abdf098 ipvs: convert the... |
965 |
return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1); |
026ace060 ipvs: optimize ds... |
966 |
} |
1da177e4c Linux-2.6.12-rc2 |
967 |
|
4115ded13 ipvs: consolidate... |
968 |
rt = skb_rtable(skb); |
d8d1f30b9 net-next: remove ... |
969 |
tdev = rt->dst.dev; |
1da177e4c Linux-2.6.12-rc2 |
970 |
|
1da177e4c Linux-2.6.12-rc2 |
971 972 973 974 |
/* * Okay, now see if we can stuff it in the buffer as-is. */ max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr); |
8052ba292 ipvs: support ipv... |
975 976 977 978 979 980 981 |
/* We only care about the df field if sysctl_pmtu_disc(ipvs) is set */ dfp = sysctl_pmtu_disc(ipvs) ? &df : NULL; skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom, &next_protocol, NULL, &dsfield, &ttl, dfp); if (IS_ERR(skb)) goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
982 |
|
aed069df0 ip_tunnel_core: i... |
983 |
if (iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET, cp->af))) |
ea1d5d775 ipvs: properly de... |
984 985 986 |
goto tx_error; skb->transport_header = skb->network_header; |
e2d1bca7e [SK_BUFF]: Use sk... |
987 988 |
skb_push(skb, sizeof(struct iphdr)); skb_reset_network_header(skb); |
1da177e4c Linux-2.6.12-rc2 |
989 |
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
1da177e4c Linux-2.6.12-rc2 |
990 991 992 |
/* * Push down and install the IPIP header. */ |
eddc9ec53 [SK_BUFF]: Introd... |
993 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
994 995 996 |
iph->version = 4; iph->ihl = sizeof(struct iphdr)>>2; iph->frag_off = df; |
8052ba292 ipvs: support ipv... |
997 998 |
iph->protocol = next_protocol; iph->tos = dsfield; |
c92f5ca2e ipvs: Remove all ... |
999 1000 |
iph->daddr = cp->daddr.ip; iph->saddr = saddr; |
8052ba292 ipvs: support ipv... |
1001 |
iph->ttl = ttl; |
b6a7719ae ipv4: hash net pt... |
1002 |
ip_select_ident(net, skb, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1003 1004 |
/* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
1005 |
skb->ignore_df = 1; |
1da177e4c Linux-2.6.12-rc2 |
1006 |
|
b8abdf098 ipvs: convert the... |
1007 |
ret = ip_vs_tunnel_xmit_prepare(skb, cp); |
f4bc17cdd ipvs: netfilter c... |
1008 |
if (ret == NF_ACCEPT) |
33224b16f ipv4, ipv6: Pass ... |
1009 |
ip_local_out(net, skb->sk, skb); |
f4bc17cdd ipvs: netfilter c... |
1010 1011 |
else if (ret == NF_DROP) kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
1012 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1013 1014 1015 1016 |
LeaveFunction(10); return NF_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
1017 |
tx_error: |
ea1d5d775 ipvs: properly de... |
1018 1019 |
if (!IS_ERR(skb)) kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
1020 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1021 1022 1023 |
LeaveFunction(10); return NF_STOLEN; } |
b3cdd2a73 IPVS: Add and bin... |
1024 1025 1026 |
#ifdef CONFIG_IP_VS_IPV6 int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
1027 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
b3cdd2a73 IPVS: Add and bin... |
1028 1029 |
{ struct rt6_info *rt; /* Route to the other host */ |
714f095f7 ipvs: IPv6 tunnel... |
1030 |
struct in6_addr saddr; /* Source for tunnel */ |
b3cdd2a73 IPVS: Add and bin... |
1031 |
struct net_device *tdev; /* Device to other host */ |
8052ba292 ipvs: support ipv... |
1032 1033 1034 1035 |
__u8 next_protocol = 0; __u32 payload_len = 0; __u8 dsfield = 0; __u8 ttl = 0; |
b3cdd2a73 IPVS: Add and bin... |
1036 1037 |
struct ipv6hdr *iph; /* Our new IP header */ unsigned int max_headroom; /* The extra header space needed */ |
4115ded13 ipvs: consolidate... |
1038 |
int ret, local; |
b3cdd2a73 IPVS: Add and bin... |
1039 1040 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
1041 |
rcu_read_lock(); |
f5745f8ae ipvs: Pass ipvs i... |
1042 1043 |
local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest, &cp->daddr.in6, |
4115ded13 ipvs: consolidate... |
1044 1045 1046 1047 1048 1049 |
&saddr, ipvsh, 1, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_TUNNEL); if (local < 0) goto tx_error; |
026ace060 ipvs: optimize ds... |
1050 1051 |
if (local) { rcu_read_unlock(); |
b8abdf098 ipvs: convert the... |
1052 |
return ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 1); |
026ace060 ipvs: optimize ds... |
1053 |
} |
b3cdd2a73 IPVS: Add and bin... |
1054 |
|
4115ded13 ipvs: consolidate... |
1055 |
rt = (struct rt6_info *) skb_dst(skb); |
d8d1f30b9 net-next: remove ... |
1056 |
tdev = rt->dst.dev; |
b3cdd2a73 IPVS: Add and bin... |
1057 |
|
b3cdd2a73 IPVS: Add and bin... |
1058 1059 1060 1061 |
/* * Okay, now see if we can stuff it in the buffer as-is. */ max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr); |
8052ba292 ipvs: support ipv... |
1062 1063 1064 1065 1066 |
skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom, &next_protocol, &payload_len, &dsfield, &ttl, NULL); if (IS_ERR(skb)) goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
1067 |
|
aed069df0 ip_tunnel_core: i... |
1068 |
if (iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET6, cp->af))) |
ea1d5d775 ipvs: properly de... |
1069 |
goto tx_error; |
714f095f7 ipvs: IPv6 tunnel... |
1070 |
skb->transport_header = skb->network_header; |
b3cdd2a73 IPVS: Add and bin... |
1071 1072 1073 1074 |
skb_push(skb, sizeof(struct ipv6hdr)); skb_reset_network_header(skb); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
b3cdd2a73 IPVS: Add and bin... |
1075 1076 1077 1078 1079 |
/* * Push down and install the IPIP header. */ iph = ipv6_hdr(skb); iph->version = 6; |
8052ba292 ipvs: support ipv... |
1080 1081 |
iph->nexthdr = next_protocol; iph->payload_len = htons(payload_len); |
b3cdd2a73 IPVS: Add and bin... |
1082 |
memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl)); |
8052ba292 ipvs: support ipv... |
1083 |
ipv6_change_dsfield(iph, 0, dsfield); |
4e3fd7a06 net: remove ipv6_... |
1084 1085 |
iph->daddr = cp->daddr.in6; iph->saddr = saddr; |
8052ba292 ipvs: support ipv... |
1086 |
iph->hop_limit = ttl; |
b3cdd2a73 IPVS: Add and bin... |
1087 1088 |
/* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
1089 |
skb->ignore_df = 1; |
b3cdd2a73 IPVS: Add and bin... |
1090 |
|
b8abdf098 ipvs: convert the... |
1091 |
ret = ip_vs_tunnel_xmit_prepare(skb, cp); |
f4bc17cdd ipvs: netfilter c... |
1092 |
if (ret == NF_ACCEPT) |
33224b16f ipv4, ipv6: Pass ... |
1093 |
ip6_local_out(cp->ipvs->net, skb->sk, skb); |
f4bc17cdd ipvs: netfilter c... |
1094 1095 |
else if (ret == NF_DROP) kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
1096 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
1097 1098 1099 1100 |
LeaveFunction(10); return NF_STOLEN; |
b3cdd2a73 IPVS: Add and bin... |
1101 |
tx_error: |
ea1d5d775 ipvs: properly de... |
1102 1103 |
if (!IS_ERR(skb)) kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
1104 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
1105 1106 1107 1108 |
LeaveFunction(10); return NF_STOLEN; } #endif |
1da177e4c Linux-2.6.12-rc2 |
1109 1110 1111 1112 1113 1114 1115 |
/* * Direct Routing transmitter * Used for ANY protocol */ int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
1116 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
1da177e4c Linux-2.6.12-rc2 |
1117 |
{ |
4115ded13 ipvs: consolidate... |
1118 |
int local; |
1da177e4c Linux-2.6.12-rc2 |
1119 1120 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
1121 |
rcu_read_lock(); |
ecfe87b88 ipvs: Pass ipvs i... |
1122 |
local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, |
4115ded13 ipvs: consolidate... |
1123 1124 |
IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | |
c63e4de2b ipvs: Add generic... |
1125 |
IP_VS_RT_MODE_KNOWN_NH, NULL, ipvsh); |
4115ded13 ipvs: consolidate... |
1126 |
if (local < 0) |
1da177e4c Linux-2.6.12-rc2 |
1127 |
goto tx_error; |
026ace060 ipvs: optimize ds... |
1128 1129 |
if (local) { rcu_read_unlock(); |
4115ded13 ipvs: consolidate... |
1130 |
return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1); |
026ace060 ipvs: optimize ds... |
1131 |
} |
1da177e4c Linux-2.6.12-rc2 |
1132 |
|
eddc9ec53 [SK_BUFF]: Introd... |
1133 |
ip_send_check(ip_hdr(skb)); |
1da177e4c Linux-2.6.12-rc2 |
1134 |
|
1da177e4c Linux-2.6.12-rc2 |
1135 |
/* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
1136 |
skb->ignore_df = 1; |
1da177e4c Linux-2.6.12-rc2 |
1137 |
|
b8abdf098 ipvs: convert the... |
1138 |
ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 0); |
026ace060 ipvs: optimize ds... |
1139 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1140 1141 1142 |
LeaveFunction(10); return NF_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
1143 1144 |
tx_error: kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
1145 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1146 1147 1148 |
LeaveFunction(10); return NF_STOLEN; } |
b3cdd2a73 IPVS: Add and bin... |
1149 1150 1151 |
#ifdef CONFIG_IP_VS_IPV6 int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, |
4115ded13 ipvs: consolidate... |
1152 |
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) |
b3cdd2a73 IPVS: Add and bin... |
1153 |
{ |
4115ded13 ipvs: consolidate... |
1154 |
int local; |
b3cdd2a73 IPVS: Add and bin... |
1155 1156 |
EnterFunction(10); |
026ace060 ipvs: optimize ds... |
1157 |
rcu_read_lock(); |
f5745f8ae ipvs: Pass ipvs i... |
1158 1159 |
local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest, &cp->daddr.in6, |
4a4739d56 ipvs: Pull out cr... |
1160 |
NULL, ipvsh, 0, |
4115ded13 ipvs: consolidate... |
1161 |
IP_VS_RT_MODE_LOCAL | |
48e8aa6e3 ipv6: Set FLOWI_F... |
1162 1163 |
IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_KNOWN_NH); |
4115ded13 ipvs: consolidate... |
1164 |
if (local < 0) |
b3cdd2a73 IPVS: Add and bin... |
1165 |
goto tx_error; |
026ace060 ipvs: optimize ds... |
1166 1167 |
if (local) { rcu_read_unlock(); |
4115ded13 ipvs: consolidate... |
1168 |
return ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 1); |
026ace060 ipvs: optimize ds... |
1169 |
} |
b3cdd2a73 IPVS: Add and bin... |
1170 1171 |
/* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
1172 |
skb->ignore_df = 1; |
b3cdd2a73 IPVS: Add and bin... |
1173 |
|
b8abdf098 ipvs: convert the... |
1174 |
ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 0); |
026ace060 ipvs: optimize ds... |
1175 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
1176 1177 1178 |
LeaveFunction(10); return NF_STOLEN; |
b3cdd2a73 IPVS: Add and bin... |
1179 1180 |
tx_error: kfree_skb(skb); |
026ace060 ipvs: optimize ds... |
1181 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
1182 1183 1184 1185 |
LeaveFunction(10); return NF_STOLEN; } #endif |
1da177e4c Linux-2.6.12-rc2 |
1186 1187 1188 1189 1190 1191 1192 |
/* * ICMP packet transmitter * called by the ip_vs_in_icmp */ int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
1193 1194 |
struct ip_vs_protocol *pp, int offset, unsigned int hooknum, struct ip_vs_iphdr *iph) |
1da177e4c Linux-2.6.12-rc2 |
1195 1196 |
{ struct rtable *rt; /* Route to the other host */ |
1da177e4c Linux-2.6.12-rc2 |
1197 |
int rc; |
fc6047676 ipvs: changes for... |
1198 |
int local; |
4115ded13 ipvs: consolidate... |
1199 |
int rt_mode, was_input; |
1da177e4c Linux-2.6.12-rc2 |
1200 1201 1202 1203 1204 1205 1206 1207 |
EnterFunction(10); /* The ICMP packet for VS/TUN, VS/DR and LOCALNODE will be forwarded directly here, because there is no need to translate address/port back */ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) { if (cp->packet_xmit) |
d4383f04d ipvs: API change ... |
1208 |
rc = cp->packet_xmit(skb, cp, pp, iph); |
1da177e4c Linux-2.6.12-rc2 |
1209 1210 1211 1212 |
else rc = NF_ACCEPT; /* do not touch skb anymore */ atomic_inc(&cp->in_pkts); |
1da177e4c Linux-2.6.12-rc2 |
1213 1214 1215 1216 1217 1218 |
goto out; } /* * mangle and send the packet here (only for VS/NAT) */ |
4115ded13 ipvs: consolidate... |
1219 |
was_input = rt_is_input_route(skb_rtable(skb)); |
1da177e4c Linux-2.6.12-rc2 |
1220 |
|
c92f5ca2e ipvs: Remove all ... |
1221 1222 1223 1224 |
/* LOCALNODE from FORWARD hook is not supported */ rt_mode = (hooknum != NF_INET_FORWARD) ? IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; |
026ace060 ipvs: optimize ds... |
1225 |
rcu_read_lock(); |
ecfe87b88 ipvs: Pass ipvs i... |
1226 |
local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, rt_mode, |
c63e4de2b ipvs: Add generic... |
1227 |
NULL, iph); |
4115ded13 ipvs: consolidate... |
1228 1229 1230 |
if (local < 0) goto tx_error; rt = skb_rtable(skb); |
fc6047676 ipvs: changes for... |
1231 1232 1233 1234 1235 |
/* * Avoid duplicate tuple in reply direction for NAT traffic * to local address when connection is sync-ed */ |
c0cd11566 net:netfilter: us... |
1236 |
#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
fc6047676 ipvs: changes for... |
1237 1238 |
if (cp->flags & IP_VS_CONN_F_SYNC && local) { enum ip_conntrack_info ctinfo; |
05b4b065a ipvs: remove sill... |
1239 |
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
fc6047676 ipvs: changes for... |
1240 1241 1242 1243 1244 1245 |
if (ct && !nf_ct_is_untracked(ct)) { IP_VS_DBG(10, "%s(): " "stopping DNAT to local address %pI4 ", __func__, &cp->daddr.ip); |
4115ded13 ipvs: consolidate... |
1246 |
goto tx_error; |
fc6047676 ipvs: changes for... |
1247 1248 1249 1250 1251 |
} } #endif /* From world but DNAT to loopback address? */ |
4115ded13 ipvs: consolidate... |
1252 |
if (local && ipv4_is_loopback(cp->daddr.ip) && was_input) { |
fc6047676 ipvs: changes for... |
1253 1254 1255 1256 |
IP_VS_DBG(1, "%s(): " "stopping DNAT to loopback %pI4 ", __func__, &cp->daddr.ip); |
4115ded13 ipvs: consolidate... |
1257 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
1258 1259 1260 |
} /* copy-on-write the packet before mangling it */ |
af1e1cf07 [IPVS]: Replace l... |
1261 |
if (!skb_make_writable(skb, offset)) |
4115ded13 ipvs: consolidate... |
1262 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
1263 |
|
d8d1f30b9 net-next: remove ... |
1264 |
if (skb_cow(skb, rt->dst.dev->hard_header_len)) |
4115ded13 ipvs: consolidate... |
1265 |
goto tx_error; |
1da177e4c Linux-2.6.12-rc2 |
1266 |
|
1da177e4c Linux-2.6.12-rc2 |
1267 1268 1269 |
ip_vs_nat_icmp(skb, pp, cp, 0); /* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
1270 |
skb->ignore_df = 1; |
1da177e4c Linux-2.6.12-rc2 |
1271 |
|
b8abdf098 ipvs: convert the... |
1272 |
rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local); |
026ace060 ipvs: optimize ds... |
1273 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1274 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1275 |
tx_error: |
026ace060 ipvs: optimize ds... |
1276 1277 |
kfree_skb(skb); rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1278 1279 1280 1281 |
rc = NF_STOLEN; out: LeaveFunction(10); return rc; |
1da177e4c Linux-2.6.12-rc2 |
1282 |
} |
b3cdd2a73 IPVS: Add and bin... |
1283 1284 1285 1286 |
#ifdef CONFIG_IP_VS_IPV6 int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, |
d4383f04d ipvs: API change ... |
1287 |
struct ip_vs_protocol *pp, int offset, unsigned int hooknum, |
4115ded13 ipvs: consolidate... |
1288 |
struct ip_vs_iphdr *ipvsh) |
b3cdd2a73 IPVS: Add and bin... |
1289 1290 |
{ struct rt6_info *rt; /* Route to the other host */ |
b3cdd2a73 IPVS: Add and bin... |
1291 |
int rc; |
fc6047676 ipvs: changes for... |
1292 |
int local; |
c92f5ca2e ipvs: Remove all ... |
1293 |
int rt_mode; |
b3cdd2a73 IPVS: Add and bin... |
1294 1295 1296 1297 1298 1299 1300 1301 |
EnterFunction(10); /* The ICMP packet for VS/TUN, VS/DR and LOCALNODE will be forwarded directly here, because there is no need to translate address/port back */ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) { if (cp->packet_xmit) |
4115ded13 ipvs: consolidate... |
1302 |
rc = cp->packet_xmit(skb, cp, pp, ipvsh); |
b3cdd2a73 IPVS: Add and bin... |
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 |
else rc = NF_ACCEPT; /* do not touch skb anymore */ atomic_inc(&cp->in_pkts); goto out; } /* * mangle and send the packet here (only for VS/NAT) */ |
c92f5ca2e ipvs: Remove all ... |
1313 1314 1315 1316 |
/* LOCALNODE from FORWARD hook is not supported */ rt_mode = (hooknum != NF_INET_FORWARD) ? IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; |
026ace060 ipvs: optimize ds... |
1317 |
rcu_read_lock(); |
f5745f8ae ipvs: Pass ipvs i... |
1318 1319 |
local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest, &cp->daddr.in6, NULL, ipvsh, 0, rt_mode); |
4115ded13 ipvs: consolidate... |
1320 1321 1322 |
if (local < 0) goto tx_error; rt = (struct rt6_info *) skb_dst(skb); |
fc6047676 ipvs: changes for... |
1323 1324 1325 1326 |
/* * Avoid duplicate tuple in reply direction for NAT traffic * to local address when connection is sync-ed */ |
c0cd11566 net:netfilter: us... |
1327 |
#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
fc6047676 ipvs: changes for... |
1328 1329 |
if (cp->flags & IP_VS_CONN_F_SYNC && local) { enum ip_conntrack_info ctinfo; |
05b4b065a ipvs: remove sill... |
1330 |
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
fc6047676 ipvs: changes for... |
1331 1332 1333 1334 1335 1336 |
if (ct && !nf_ct_is_untracked(ct)) { IP_VS_DBG(10, "%s(): " "stopping DNAT to local address %pI6 ", __func__, &cp->daddr.in6); |
4115ded13 ipvs: consolidate... |
1337 |
goto tx_error; |
fc6047676 ipvs: changes for... |
1338 1339 1340 1341 1342 1343 |
} } #endif /* From world but DNAT to loopback address? */ if (local && skb->dev && !(skb->dev->flags & IFF_LOOPBACK) && |
fd0273d79 ipv6: Remove exte... |
1344 |
ipv6_addr_type(&cp->daddr.in6) & IPV6_ADDR_LOOPBACK) { |
fc6047676 ipvs: changes for... |
1345 1346 1347 1348 |
IP_VS_DBG(1, "%s(): " "stopping DNAT to loopback %pI6 ", __func__, &cp->daddr.in6); |
4115ded13 ipvs: consolidate... |
1349 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
1350 1351 1352 1353 |
} /* copy-on-write the packet before mangling it */ if (!skb_make_writable(skb, offset)) |
4115ded13 ipvs: consolidate... |
1354 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
1355 |
|
d8d1f30b9 net-next: remove ... |
1356 |
if (skb_cow(skb, rt->dst.dev->hard_header_len)) |
4115ded13 ipvs: consolidate... |
1357 |
goto tx_error; |
b3cdd2a73 IPVS: Add and bin... |
1358 |
|
b3cdd2a73 IPVS: Add and bin... |
1359 1360 1361 |
ip_vs_nat_icmp_v6(skb, pp, cp, 0); /* Another hack: avoid icmp_send in ip_fragment */ |
60ff74673 net: rename local... |
1362 |
skb->ignore_df = 1; |
b3cdd2a73 IPVS: Add and bin... |
1363 |
|
b8abdf098 ipvs: convert the... |
1364 |
rc = ip_vs_nat_send_or_cont(NFPROTO_IPV6, skb, cp, local); |
026ace060 ipvs: optimize ds... |
1365 |
rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
1366 |
goto out; |
b3cdd2a73 IPVS: Add and bin... |
1367 |
tx_error: |
026ace060 ipvs: optimize ds... |
1368 1369 |
kfree_skb(skb); rcu_read_unlock(); |
b3cdd2a73 IPVS: Add and bin... |
1370 1371 1372 1373 |
rc = NF_STOLEN; out: LeaveFunction(10); return rc; |
b3cdd2a73 IPVS: Add and bin... |
1374 1375 |
} #endif |