Blame view

net/netfilter/ipvs/ip_vs_xmit.c 35.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * ip_vs_xmit.c: various packet transmitters for IPVS
   *
1da177e4c   Linus Torvalds   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   Julian Anastasov   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   Julian Anastasov   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   Julian Anastasov   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   Linus Torvalds   Linux-2.6.12-rc2
26
   */
9aada7ac0   Hannes Eder   IPVS: use pr_fmt
27
28
  #define KMSG_COMPONENT "IPVS"
  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
30
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  #include <linux/tcp.h>                  /* for tcphdr */
c439cb2e4   Herbert Xu   [IPV4]: Add ip_lo...
32
  #include <net/ip.h>
1da177e4c   Linus Torvalds   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   Julius Volz   IPVS: Add IPv6 su...
37
38
  #include <net/ipv6.h>
  #include <net/ip6_route.h>
ea1d5d775   Julian Anastasov   ipvs: properly de...
39
  #include <net/ip_tunnels.h>
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
40
  #include <net/addrconf.h>
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
41
  #include <linux/icmpv6.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
  #include <linux/netfilter.h>
  #include <linux/netfilter_ipv4.h>
  
  #include <net/ip_vs.h>
17a8f8e37   Changli Gao   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   Julian Anastasov   ipvs: implement p...
52
  	IP_VS_RT_MODE_CONNECT	= 8, /* Always bind route to saddr */
ad4d3ef8b   Julian Anastasov   ipvs: fix ARP res...
53
  	IP_VS_RT_MODE_KNOWN_NH	= 16,/* Route via remote addr */
4115ded13   Julian Anastasov   ipvs: consolidate...
54
  	IP_VS_RT_MODE_TUNNEL	= 32,/* Tunnel mode */
17a8f8e37   Changli Gao   ipvs: use enum to...
55
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56

026ace060   Julian Anastasov   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   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
  /*
   *      Destination cache to speed up outgoing route lookup
   */
  static inline void
026ace060   Julian Anastasov   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   Linus Torvalds   Linux-2.6.12-rc2
72
  {
026ace060   Julian Anastasov   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   Linus Torvalds   Linux-2.6.12-rc2
83

026ace060   Julian Anastasov   ipvs: optimize ds...
84
85
  	if (old)
  		call_rcu(&old->rcu_head, ip_vs_dest_dst_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  }
026ace060   Julian Anastasov   ipvs: optimize ds...
87
  static inline struct ip_vs_dest_dst *
c90558dae   Julian Anastasov   ipvs: avoid routi...
88
  __ip_vs_dst_check(struct ip_vs_dest *dest)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
026ace060   Julian Anastasov   ipvs: optimize ds...
90
91
  	struct ip_vs_dest_dst *dest_dst = rcu_dereference(dest->dest_dst);
  	struct dst_entry *dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92

026ace060   Julian Anastasov   ipvs: optimize ds...
93
  	if (!dest_dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  		return NULL;
026ace060   Julian Anastasov   ipvs: optimize ds...
95
96
97
  	dst = dest_dst->dst_cache;
  	if (dst->obsolete &&
  	    dst->ops->check(dst, dest_dst->dst_cookie) == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  		return NULL;
026ace060   Julian Anastasov   ipvs: optimize ds...
99
  	return dest_dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  }
590e3f79a   Jesper Dangaard Brouer   ipvs: IPv6 MTU ch...
101
102
103
  static inline bool
  __mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
  {
4cdd34084   Patrick McHardy   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   Jesper Dangaard Brouer   ipvs: IPv6 MTU ch...
112
113
114
115
  		return true; /* Packet size violate MTU size */
  	}
  	return false;
  }
f2edb9f77   Julian Anastasov   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   Julian Anastasov   ipvs: avoid routi...
118
  				       int rt_mode, __be32 *saddr)
f2edb9f77   Julian Anastasov   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   Julian Anastasov   ipvs: fix ARP res...
126
127
  	fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
  			   FLOWI_FLAG_KNOWN_NH : 0;
f2edb9f77   Julian Anastasov   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   Julian Anastasov   ipvs: avoid routi...
136
  			flowi4_update_output(&fl4, 0, 0, daddr, 0);
f2edb9f77   Julian Anastasov   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   Julian Anastasov   ipvs: avoid routi...
145
  		flowi4_update_output(&fl4, 0, 0, daddr, fl4.saddr);
f2edb9f77   Julian Anastasov   ipvs: implement p...
146
147
148
149
150
151
  		loop++;
  		goto retry;
  	}
  	*saddr = fl4.saddr;
  	return rt;
  }
4a4739d56   Alex Gartrell   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   Alex Gartrell   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   Eric Dumazet   netfilter: use sk...
202
  	if (!skb->dev && sk && sk_fullsock(sk))
919aa0b2b   Alex Gartrell   ipvs: Pull out up...
203
204
  		ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu);
  }
20868a40d   Eric W. Biederman   ipvs: Pass ipvs i...
205
206
  static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af,
  					  int rt_mode,
c63e4de2b   Alex Gartrell   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   Eric W. Biederman   ipvs: Pass ipvs i...
212
  		struct net *net = ipvs->net;
c63e4de2b   Alex Gartrell   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   Alex Gartrell   ipvs: ensure that...
218
  			if (!ipvsh->fragoffs && !ip_vs_iph_icmp(ipvsh))
c63e4de2b   Alex Gartrell   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   Alex Gartrell   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   Alex Gartrell   ipvs: ensure that...
235
236
  			     skb->len > mtu && !skb_is_gso(skb) &&
  			     !ip_vs_iph_icmp(ipvsh))) {
c63e4de2b   Alex Gartrell   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   Changli Gao   ipvs: use enum to...
248
  /* Get route to destination or remote server */
4115ded13   Julian Anastasov   ipvs: consolidate...
249
  static int
ecfe87b88   Eric W. Biederman   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   Alex Gartrell   ipvs: Add generic...
252
253
  		   __be32 daddr, int rt_mode, __be32 *ret_saddr,
  		   struct ip_vs_iphdr *ipvsh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  {
ecfe87b88   Eric W. Biederman   ipvs: Pass ipvs i...
255
  	struct net *net = ipvs->net;
026ace060   Julian Anastasov   ipvs: optimize ds...
256
  	struct ip_vs_dest_dst *dest_dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  	struct rtable *rt;			/* Route to the other host */
4115ded13   Julian Anastasov   ipvs: consolidate...
258
  	int mtu;
026ace060   Julian Anastasov   ipvs: optimize ds...
259
  	int local, noref = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
  
  	if (dest) {
026ace060   Julian Anastasov   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   Julian Anastasov   ipvs: do not disa...
267
  			spin_lock_bh(&dest->dst_lock);
026ace060   Julian Anastasov   ipvs: optimize ds...
268
269
  			if (!dest_dst) {
  				__ip_vs_dst_set(dest, NULL, NULL, 0);
ac69269a4   Julian Anastasov   ipvs: do not disa...
270
  				spin_unlock_bh(&dest->dst_lock);
026ace060   Julian Anastasov   ipvs: optimize ds...
271
272
  				goto err_unreach;
  			}
c90558dae   Julian Anastasov   ipvs: avoid routi...
273
  			rt = do_output_route4(net, dest->addr.ip, rt_mode,
026ace060   Julian Anastasov   ipvs: optimize ds...
274
  					      &dest_dst->dst_saddr.ip);
f2edb9f77   Julian Anastasov   ipvs: implement p...
275
  			if (!rt) {
026ace060   Julian Anastasov   ipvs: optimize ds...
276
  				__ip_vs_dst_set(dest, NULL, NULL, 0);
ac69269a4   Julian Anastasov   ipvs: do not disa...
277
  				spin_unlock_bh(&dest->dst_lock);
026ace060   Julian Anastasov   ipvs: optimize ds...
278
  				ip_vs_dest_dst_free(dest_dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
279
  				goto err_unreach;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  			}
026ace060   Julian Anastasov   ipvs: optimize ds...
281
  			__ip_vs_dst_set(dest, dest_dst, &rt->dst, 0);
ac69269a4   Julian Anastasov   ipvs: do not disa...
282
  			spin_unlock_bh(&dest->dst_lock);
c90558dae   Julian Anastasov   ipvs: avoid routi...
283
284
  			IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d
  ",
026ace060   Julian Anastasov   ipvs: optimize ds...
285
  				  &dest->addr.ip, &dest_dst->dst_saddr.ip,
c90558dae   Julian Anastasov   ipvs: avoid routi...
286
  				  atomic_read(&rt->dst.__refcnt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  		}
c92f5ca2e   Julian Anastasov   ipvs: Remove all ...
288
  		if (ret_saddr)
026ace060   Julian Anastasov   ipvs: optimize ds...
289
  			*ret_saddr = dest_dst->dst_saddr.ip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  	} else {
f2edb9f77   Julian Anastasov   ipvs: implement p...
291
  		__be32 saddr = htonl(INADDR_ANY);
c92f5ca2e   Julian Anastasov   ipvs: Remove all ...
292

026ace060   Julian Anastasov   ipvs: optimize ds...
293
  		noref = 0;
f2edb9f77   Julian Anastasov   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   Julian Anastasov   ipvs: avoid routi...
298
  		rt = do_output_route4(net, daddr, rt_mode, &saddr);
f2edb9f77   Julian Anastasov   ipvs: implement p...
299
  		if (!rt)
4115ded13   Julian Anastasov   ipvs: consolidate...
300
  			goto err_unreach;
c92f5ca2e   Julian Anastasov   ipvs: Remove all ...
301
  		if (ret_saddr)
f2edb9f77   Julian Anastasov   ipvs: implement p...
302
  			*ret_saddr = saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  	}
4115ded13   Julian Anastasov   ipvs: consolidate...
304
  	local = (rt->rt_flags & RTCF_LOCAL) ? 1 : 0;
4a4739d56   Alex Gartrell   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   Alex Gartrell   ipvs: Avoid null-...
308
309
  			     " daddr=%pI4
  ", &daddr);
4115ded13   Julian Anastasov   ipvs: consolidate...
310
  		goto err_put;
fc6047676   Julian Anastasov   ipvs: changes for...
311
  	}
4a4739d56   Alex Gartrell   ipvs: Pull out cr...
312
313
  
  	if (unlikely(local)) {
4115ded13   Julian Anastasov   ipvs: consolidate...
314
  		/* skb to local stack, preserve old route */
026ace060   Julian Anastasov   ipvs: optimize ds...
315
316
  		if (!noref)
  			ip_rt_put(rt);
4115ded13   Julian Anastasov   ipvs: consolidate...
317
  		return local;
fc6047676   Julian Anastasov   ipvs: changes for...
318
  	}
4115ded13   Julian Anastasov   ipvs: consolidate...
319
320
321
  
  	if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
  		mtu = dst_mtu(&rt->dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
322
  	} else {
4115ded13   Julian Anastasov   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   Alex Gartrell   ipvs: Pull out up...
329
  		maybe_update_pmtu(skb_af, skb, mtu);
fc6047676   Julian Anastasov   ipvs: changes for...
330
  	}
20868a40d   Eric W. Biederman   ipvs: Pass ipvs i...
331
  	if (!ensure_mtu_is_adequate(ipvs, skb_af, rt_mode, ipvsh, skb, mtu))
4115ded13   Julian Anastasov   ipvs: consolidate...
332
  		goto err_put;
4115ded13   Julian Anastasov   ipvs: consolidate...
333
334
  
  	skb_dst_drop(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
335
336
  	if (noref) {
  		if (!local)
dbfc4fb7d   Hannes Frederic Sowa   dst: no need to t...
337
  			skb_dst_set_noref(skb, &rt->dst);
026ace060   Julian Anastasov   ipvs: optimize ds...
338
339
340
341
  		else
  			skb_dst_set(skb, dst_clone(&rt->dst));
  	} else
  		skb_dst_set(skb, &rt->dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
342
343
344
345
  
  	return local;
  
  err_put:
026ace060   Julian Anastasov   ipvs: optimize ds...
346
347
  	if (!noref)
  		ip_rt_put(rt);
4115ded13   Julian Anastasov   ipvs: consolidate...
348
349
350
351
352
  	return -1;
  
  err_unreach:
  	dst_link_failure(skb);
  	return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  }
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
354
  #ifdef CONFIG_IP_VS_IPV6
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
355
356
  static struct dst_entry *
  __ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr,
48e8aa6e3   Martin KaFai Lau   ipv6: Set FLOWI_F...
357
  			struct in6_addr *ret_saddr, int do_xfrm, int rt_mode)
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
358
359
  {
  	struct dst_entry *dst;
4c9483b2f   David S. Miller   ipv6: Convert to ...
360
361
  	struct flowi6 fl6 = {
  		.daddr = *daddr,
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
362
  	};
48e8aa6e3   Martin KaFai Lau   ipv6: Set FLOWI_F...
363
364
  	if (rt_mode & IP_VS_RT_MODE_KNOWN_NH)
  		fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
4c9483b2f   David S. Miller   ipv6: Convert to ...
365
  	dst = ip6_route_output(net, NULL, &fl6);
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
366
367
368
369
  	if (dst->error)
  		goto out_err;
  	if (!ret_saddr)
  		return dst;
4c9483b2f   David S. Miller   ipv6: Convert to ...
370
  	if (ipv6_addr_any(&fl6.saddr) &&
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
371
  	    ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev,
4c9483b2f   David S. Miller   ipv6: Convert to ...
372
  			       &fl6.daddr, 0, &fl6.saddr) < 0)
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
373
  		goto out_err;
452edd598   David S. Miller   xfrm: Return dst ...
374
  	if (do_xfrm) {
4c9483b2f   David S. Miller   ipv6: Convert to ...
375
  		dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
452edd598   David S. Miller   xfrm: Return dst ...
376
377
378
379
380
  		if (IS_ERR(dst)) {
  			dst = NULL;
  			goto out_err;
  		}
  	}
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
381
  	*ret_saddr = fl6.saddr;
714f095f7   Hans Schillstrom   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   Julian Anastasov   ipvs: changes for...
390
391
  /*
   * Get route to destination or remote server
fc6047676   Julian Anastasov   ipvs: changes for...
392
   */
4115ded13   Julian Anastasov   ipvs: consolidate...
393
  static int
f5745f8ae   Eric W. Biederman   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   Julian Anastasov   ipvs: changes for...
396
  		      struct in6_addr *daddr, struct in6_addr *ret_saddr,
4115ded13   Julian Anastasov   ipvs: consolidate...
397
  		      struct ip_vs_iphdr *ipvsh, int do_xfrm, int rt_mode)
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
398
  {
f5745f8ae   Eric W. Biederman   ipvs: Pass ipvs i...
399
  	struct net *net = ipvs->net;
026ace060   Julian Anastasov   ipvs: optimize ds...
400
  	struct ip_vs_dest_dst *dest_dst;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
401
  	struct rt6_info *rt;			/* Route to the other host */
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
402
  	struct dst_entry *dst;
4115ded13   Julian Anastasov   ipvs: consolidate...
403
  	int mtu;
026ace060   Julian Anastasov   ipvs: optimize ds...
404
  	int local, noref = 1;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
405
406
  
  	if (dest) {
026ace060   Julian Anastasov   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   Hans Schillstrom   ipvs: IPv6 tunnel...
411
  			u32 cookie;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
412

026ace060   Julian Anastasov   ipvs: optimize ds...
413
  			dest_dst = ip_vs_dest_dst_alloc();
ac69269a4   Julian Anastasov   ipvs: do not disa...
414
  			spin_lock_bh(&dest->dst_lock);
026ace060   Julian Anastasov   ipvs: optimize ds...
415
416
  			if (!dest_dst) {
  				__ip_vs_dst_set(dest, NULL, NULL, 0);
ac69269a4   Julian Anastasov   ipvs: do not disa...
417
  				spin_unlock_bh(&dest->dst_lock);
026ace060   Julian Anastasov   ipvs: optimize ds...
418
419
  				goto err_unreach;
  			}
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
420
  			dst = __ip_vs_route_output_v6(net, &dest->addr.in6,
026ace060   Julian Anastasov   ipvs: optimize ds...
421
  						      &dest_dst->dst_saddr.in6,
48e8aa6e3   Martin KaFai Lau   ipv6: Set FLOWI_F...
422
  						      do_xfrm, rt_mode);
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
423
  			if (!dst) {
026ace060   Julian Anastasov   ipvs: optimize ds...
424
  				__ip_vs_dst_set(dest, NULL, NULL, 0);
ac69269a4   Julian Anastasov   ipvs: do not disa...
425
  				spin_unlock_bh(&dest->dst_lock);
026ace060   Julian Anastasov   ipvs: optimize ds...
426
  				ip_vs_dest_dst_free(dest_dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
427
  				goto err_unreach;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
428
  			}
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
429
  			rt = (struct rt6_info *) dst;
b197df4f0   Martin KaFai Lau   ipv6: Add rt6_get...
430
  			cookie = rt6_get_cookie(rt);
026ace060   Julian Anastasov   ipvs: optimize ds...
431
  			__ip_vs_dst_set(dest, dest_dst, &rt->dst, cookie);
ac69269a4   Julian Anastasov   ipvs: do not disa...
432
  			spin_unlock_bh(&dest->dst_lock);
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
433
434
  			IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d
  ",
026ace060   Julian Anastasov   ipvs: optimize ds...
435
  				  &dest->addr.in6, &dest_dst->dst_saddr.in6,
d8d1f30b9   Changli Gao   net-next: remove ...
436
  				  atomic_read(&rt->dst.__refcnt));
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
437
  		}
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
438
  		if (ret_saddr)
026ace060   Julian Anastasov   ipvs: optimize ds...
439
  			*ret_saddr = dest_dst->dst_saddr.in6;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
440
  	} else {
026ace060   Julian Anastasov   ipvs: optimize ds...
441
  		noref = 0;
48e8aa6e3   Martin KaFai Lau   ipv6: Set FLOWI_F...
442
443
  		dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm,
  					      rt_mode);
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
444
  		if (!dst)
4115ded13   Julian Anastasov   ipvs: consolidate...
445
  			goto err_unreach;
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
446
  		rt = (struct rt6_info *) dst;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
447
  	}
fc6047676   Julian Anastasov   ipvs: changes for...
448
  	local = __ip_vs_is_local_route6(rt);
4a4739d56   Alex Gartrell   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   Alex Gartrell   ipvs: Avoid null-...
453
454
  			     " daddr=%pI6
  ", daddr);
4115ded13   Julian Anastasov   ipvs: consolidate...
455
  		goto err_put;
fc6047676   Julian Anastasov   ipvs: changes for...
456
  	}
4a4739d56   Alex Gartrell   ipvs: Pull out cr...
457
458
  
  	if (unlikely(local)) {
4115ded13   Julian Anastasov   ipvs: consolidate...
459
  		/* skb to local stack, preserve old route */
026ace060   Julian Anastasov   ipvs: optimize ds...
460
461
  		if (!noref)
  			dst_release(&rt->dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
462
  		return local;
fc6047676   Julian Anastasov   ipvs: changes for...
463
  	}
4115ded13   Julian Anastasov   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   Julian Anastasov   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   Alex Gartrell   ipvs: Pull out up...
476
  		maybe_update_pmtu(skb_af, skb, mtu);
fc6047676   Julian Anastasov   ipvs: changes for...
477
  	}
20868a40d   Eric W. Biederman   ipvs: Pass ipvs i...
478
  	if (!ensure_mtu_is_adequate(ipvs, skb_af, rt_mode, ipvsh, skb, mtu))
4115ded13   Julian Anastasov   ipvs: consolidate...
479
  		goto err_put;
4115ded13   Julian Anastasov   ipvs: consolidate...
480
481
  
  	skb_dst_drop(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
482
483
  	if (noref) {
  		if (!local)
dbfc4fb7d   Hannes Frederic Sowa   dst: no need to t...
484
  			skb_dst_set_noref(skb, &rt->dst);
026ace060   Julian Anastasov   ipvs: optimize ds...
485
486
487
488
  		else
  			skb_dst_set(skb, dst_clone(&rt->dst));
  	} else
  		skb_dst_set(skb, &rt->dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
489
490
491
492
  
  	return local;
  
  err_put:
026ace060   Julian Anastasov   ipvs: optimize ds...
493
494
  	if (!noref)
  		dst_release(&rt->dst);
4115ded13   Julian Anastasov   ipvs: consolidate...
495
496
497
  	return -1;
  
  err_unreach:
326bf17ea   Alex Gartrell   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   Julian Anastasov   ipvs: consolidate...
504
505
  	dst_link_failure(skb);
  	return -1;
38cdcc9a0   Julius Volz   IPVS: Add IPv6 su...
506
507
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508

b8abdf098   Julian Anastasov   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   Alex Gartrell   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   Julian Anastasov   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   Alex Gartrell   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   Julian Anastasov   ipvs: convert the...
556
557
  	if (!local) {
  		skb_forward_csum(skb);
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
558
  		NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb,
13206b6bf   Eric W. Biederman   net: Pass net int...
559
  			NULL, skb_dst(skb)->dev, dst_output);
b8abdf098   Julian Anastasov   ipvs: convert the...
560
561
  	} else
  		ret = NF_ACCEPT;
71563f341   Alex Gartrell   ipvs: skb_orphan ...
562

b8abdf098   Julian Anastasov   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   Alex Gartrell   ipvs: skb_orphan ...
576
  		ip_vs_drop_early_demux_sk(skb);
b8abdf098   Julian Anastasov   ipvs: convert the...
577
  		skb_forward_csum(skb);
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
578
  		NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb,
13206b6bf   Eric W. Biederman   net: Pass net int...
579
  			NULL, skb_dst(skb)->dev, dst_output);
b8abdf098   Julian Anastasov   ipvs: convert the...
580
581
582
583
  	} else
  		ret = NF_ACCEPT;
  	return ret;
  }
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
591
  		struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
  {
  	/* we do not touch skb and do not need pskb ptr */
b8abdf098   Julian Anastasov   ipvs: convert the...
594
  	return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1);
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
605
  		  struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
607
  	struct iphdr  *iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
609
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
610
  	rcu_read_lock();
ecfe87b88   Eric W. Biederman   ipvs: Pass ipvs i...
611
  	if (__ip_vs_get_out_rt(cp->ipvs, cp->af, skb, NULL, iph->daddr,
c63e4de2b   Alex Gartrell   ipvs: Add generic...
612
  			       IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614

4115ded13   Julian Anastasov   ipvs: consolidate...
615
  	ip_send_check(iph);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
  
  	/* Another hack: avoid icmp_send in ip_fragment */
60ff74673   WANG Cong   net: rename local...
618
  	skb->ignore_df = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619

b8abdf098   Julian Anastasov   ipvs: convert the...
620
  	ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 0);
026ace060   Julian Anastasov   ipvs: optimize ds...
621
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
624
  
  	LeaveFunction(10);
  	return NF_STOLEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
   tx_error:
  	kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
627
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
629
630
  	LeaveFunction(10);
  	return NF_STOLEN;
  }
b3cdd2a73   Julius Volz   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   Julian Anastasov   ipvs: consolidate...
634
  		     struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
635
  {
3481894fc   Alex Gartrell   ipvs: Use outer h...
636
  	struct ipv6hdr *iph = ipv6_hdr(skb);
b3cdd2a73   Julius Volz   IPVS: Add and bin...
637
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
638
  	rcu_read_lock();
f5745f8ae   Eric W. Biederman   ipvs: Pass ipvs i...
639
640
  	if (__ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, NULL,
  				  &iph->daddr, NULL,
4115ded13   Julian Anastasov   ipvs: consolidate...
641
  				  ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL) < 0)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
642
  		goto tx_error;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
643
644
  
  	/* Another hack: avoid icmp_send in ip_fragment */
60ff74673   WANG Cong   net: rename local...
645
  	skb->ignore_df = 1;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
646

b8abdf098   Julian Anastasov   ipvs: convert the...
647
  	ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 0);
026ace060   Julian Anastasov   ipvs: optimize ds...
648
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
649
650
651
  
  	LeaveFunction(10);
  	return NF_STOLEN;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
652
653
   tx_error:
  	kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
654
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
655
656
657
658
  	LeaveFunction(10);
  	return NF_STOLEN;
  }
  #endif
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
666
  	       struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
  {
  	struct rtable *rt;		/* Route to the other host */
4115ded13   Julian Anastasov   ipvs: consolidate...
669
  	int local, rc, was_input;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
671
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
672
  	rcu_read_lock();
1da177e4c   Linus Torvalds   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   Al Viro   [IPVS]: ipvs anno...
675
  		__be16 _pt, *p;
4115ded13   Julian Anastasov   ipvs: consolidate...
676
677
  
  		p = skb_header_pointer(skb, ipvsh->len, sizeof(_pt), &_pt);
1da177e4c   Linus Torvalds   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   Julian Anastasov   ipvs: consolidate...
684
  	was_input = rt_is_input_route(skb_rtable(skb));
ecfe87b88   Eric W. Biederman   ipvs: Pass ipvs i...
685
  	local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip,
4115ded13   Julian Anastasov   ipvs: consolidate...
686
687
  				   IP_VS_RT_MODE_LOCAL |
  				   IP_VS_RT_MODE_NON_LOCAL |
c63e4de2b   Alex Gartrell   ipvs: Add generic...
688
  				   IP_VS_RT_MODE_RDR, NULL, ipvsh);
4115ded13   Julian Anastasov   ipvs: consolidate...
689
690
691
  	if (local < 0)
  		goto tx_error;
  	rt = skb_rtable(skb);
fc6047676   Julian Anastasov   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   Igor Maravić   net:netfilter: us...
696
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
fc6047676   Julian Anastasov   ipvs: changes for...
697
698
  	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
  		enum ip_conntrack_info ctinfo;
05b4b065a   Alan Cox   ipvs: remove sill...
699
  		struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
fc6047676   Julian Anastasov   ipvs: changes for...
700
701
  
  		if (ct && !nf_ct_is_untracked(ct)) {
b0e010c52   Alex Gartrell   ipvs: replace ip_...
702
  			IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, ipvsh->off,
0d79641a9   Julian Anastasov   ipvs: provide add...
703
  					 "ip_vs_nat_xmit(): "
fc6047676   Julian Anastasov   ipvs: changes for...
704
  					 "stopping DNAT to local address");
4115ded13   Julian Anastasov   ipvs: consolidate...
705
  			goto tx_error;
fc6047676   Julian Anastasov   ipvs: changes for...
706
707
708
709
710
  		}
  	}
  #endif
  
  	/* From world but DNAT to loopback address? */
4115ded13   Julian Anastasov   ipvs: consolidate...
711
  	if (local && ipv4_is_loopback(cp->daddr.ip) && was_input) {
b0e010c52   Alex Gartrell   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   Julian Anastasov   ipvs: consolidate...
715
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
718
  	}
  
  	/* copy-on-write the packet before mangling it */
af1e1cf07   Herbert Xu   [IPVS]: Replace l...
719
  	if (!skb_make_writable(skb, sizeof(struct iphdr)))
4115ded13   Julian Anastasov   ipvs: consolidate...
720
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721

d8d1f30b9   Changli Gao   net-next: remove ...
722
  	if (skb_cow(skb, rt->dst.dev->hard_header_len))
4115ded13   Julian Anastasov   ipvs: consolidate...
723
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
  	/* mangle the packet */
d4383f04d   Jesper Dangaard Brouer   ipvs: API change ...
726
  	if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, ipvsh))
4115ded13   Julian Anastasov   ipvs: consolidate...
727
  		goto tx_error;
e7ade46a5   Julius Volz   IPVS: Change IPVS...
728
  	ip_hdr(skb)->daddr = cp->daddr.ip;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
729
  	ip_send_check(ip_hdr(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730

b0e010c52   Alex Gartrell   ipvs: replace ip_...
731
  	IP_VS_DBG_PKT(10, AF_INET, pp, skb, ipvsh->off, "After DNAT");
1da177e4c   Linus Torvalds   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   WANG Cong   net: rename local...
738
  	skb->ignore_df = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739

b8abdf098   Julian Anastasov   ipvs: convert the...
740
  	rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local);
026ace060   Julian Anastasov   ipvs: optimize ds...
741
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
  
  	LeaveFunction(10);
b8abdf098   Julian Anastasov   ipvs: convert the...
744
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
    tx_error:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
  	kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
748
  	rcu_read_unlock();
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
749
  	LeaveFunction(10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  	return NF_STOLEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
  }
b3cdd2a73   Julius Volz   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   Julian Anastasov   ipvs: consolidate...
755
  		  struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
756
757
  {
  	struct rt6_info *rt;		/* Route to the other host */
b8abdf098   Julian Anastasov   ipvs: convert the...
758
  	int local, rc;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
759
760
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
761
  	rcu_read_lock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
762
  	/* check if it is a connection of no-client-port */
4115ded13   Julian Anastasov   ipvs: consolidate...
763
  	if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT && !ipvsh->fragoffs)) {
b3cdd2a73   Julius Volz   IPVS: Add and bin...
764
  		__be16 _pt, *p;
4115ded13   Julian Anastasov   ipvs: consolidate...
765
  		p = skb_header_pointer(skb, ipvsh->len, sizeof(_pt), &_pt);
b3cdd2a73   Julius Volz   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   Eric W. Biederman   ipvs: Pass ipvs i...
772
773
  	local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest,
  				      &cp->daddr.in6,
4a4739d56   Alex Gartrell   ipvs: Pull out cr...
774
  				      NULL, ipvsh, 0,
4115ded13   Julian Anastasov   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   Julian Anastasov   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   Igor Maravić   net:netfilter: us...
785
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
fc6047676   Julian Anastasov   ipvs: changes for...
786
787
  	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
  		enum ip_conntrack_info ctinfo;
05b4b065a   Alan Cox   ipvs: remove sill...
788
  		struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
fc6047676   Julian Anastasov   ipvs: changes for...
789
790
  
  		if (ct && !nf_ct_is_untracked(ct)) {
b0e010c52   Alex Gartrell   ipvs: replace ip_...
791
  			IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, ipvsh->off,
fc6047676   Julian Anastasov   ipvs: changes for...
792
793
  					 "ip_vs_nat_xmit_v6(): "
  					 "stopping DNAT to local address");
4115ded13   Julian Anastasov   ipvs: consolidate...
794
  			goto tx_error;
fc6047676   Julian Anastasov   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   Martin KaFai Lau   ipv6: Remove exte...
801
  	    ipv6_addr_type(&cp->daddr.in6) & IPV6_ADDR_LOOPBACK) {
b0e010c52   Alex Gartrell   ipvs: replace ip_...
802
  		IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, ipvsh->off,
fc6047676   Julian Anastasov   ipvs: changes for...
803
804
  				 "ip_vs_nat_xmit_v6(): "
  				 "stopping DNAT to loopback address");
4115ded13   Julian Anastasov   ipvs: consolidate...
805
  		goto tx_error;
b3cdd2a73   Julius Volz   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   Julian Anastasov   ipvs: consolidate...
810
  		goto tx_error;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
811

d8d1f30b9   Changli Gao   net-next: remove ...
812
  	if (skb_cow(skb, rt->dst.dev->hard_header_len))
4115ded13   Julian Anastasov   ipvs: consolidate...
813
  		goto tx_error;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
814

b3cdd2a73   Julius Volz   IPVS: Add and bin...
815
  	/* mangle the packet */
4115ded13   Julian Anastasov   ipvs: consolidate...
816
  	if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, ipvsh))
b3cdd2a73   Julius Volz   IPVS: Add and bin...
817
  		goto tx_error;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
818
  	ipv6_hdr(skb)->daddr = cp->daddr.in6;
fc6047676   Julian Anastasov   ipvs: changes for...
819

b0e010c52   Alex Gartrell   ipvs: replace ip_...
820
  	IP_VS_DBG_PKT(10, AF_INET6, pp, skb, ipvsh->off, "After DNAT");
b3cdd2a73   Julius Volz   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   WANG Cong   net: rename local...
827
  	skb->ignore_df = 1;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
828

b8abdf098   Julian Anastasov   ipvs: convert the...
829
  	rc = ip_vs_nat_send_or_cont(NFPROTO_IPV6, skb, cp, local);
026ace060   Julian Anastasov   ipvs: optimize ds...
830
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
831
832
  
  	LeaveFunction(10);
b8abdf098   Julian Anastasov   ipvs: convert the...
833
  	return rc;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
834

b3cdd2a73   Julius Volz   IPVS: Add and bin...
835
836
837
  tx_error:
  	LeaveFunction(10);
  	kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
838
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
839
  	return NF_STOLEN;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
840
841
  }
  #endif
8052ba292   Alex Gartrell   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   Alex Gartrell   ipvs: skb_orphan ...
859
  	ip_vs_drop_early_demux_sk(skb);
8052ba292   Alex Gartrell   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   Calvin Owens   ipvs: Keep skb->s...
864
865
  		if (skb->sk)
  			skb_set_owner_w(new_skb, skb->sk);
8052ba292   Alex Gartrell   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   Tom Herbert   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   Alex Gartrell   ipvs: support ipv...
914
  	}
8052ba292   Alex Gartrell   ipvs: support ipv...
915
  }
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
938
  		  struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  {
361c3f529   Eric W. Biederman   ipvs: Better deri...
940
941
  	struct netns_ipvs *ipvs = cp->ipvs;
  	struct net *net = ipvs->net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
  	struct rtable *rt;			/* Route to the other host */
c92f5ca2e   Julian Anastasov   ipvs: Remove all ...
943
  	__be32 saddr;				/* Source for tunnel */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
  	struct net_device *tdev;		/* Device to other host */
8052ba292   Alex Gartrell   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   Linus Torvalds   Linux-2.6.12-rc2
950
  	struct iphdr  *iph;			/* Our new IP header */
c2636b4d9   Chuck Lever   [NET]: Treat the ...
951
  	unsigned int max_headroom;		/* The extra header space needed */
4115ded13   Julian Anastasov   ipvs: consolidate...
952
  	int ret, local;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
955
  	rcu_read_lock();
ecfe87b88   Eric W. Biederman   ipvs: Pass ipvs i...
956
  	local = __ip_vs_get_out_rt(ipvs, cp->af, skb, cp->dest, cp->daddr.ip,
4115ded13   Julian Anastasov   ipvs: consolidate...
957
958
959
  				   IP_VS_RT_MODE_LOCAL |
  				   IP_VS_RT_MODE_NON_LOCAL |
  				   IP_VS_RT_MODE_CONNECT |
c63e4de2b   Alex Gartrell   ipvs: Add generic...
960
  				   IP_VS_RT_MODE_TUNNEL, &saddr, ipvsh);
4115ded13   Julian Anastasov   ipvs: consolidate...
961
962
  	if (local < 0)
  		goto tx_error;
026ace060   Julian Anastasov   ipvs: optimize ds...
963
964
  	if (local) {
  		rcu_read_unlock();
b8abdf098   Julian Anastasov   ipvs: convert the...
965
  		return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1);
026ace060   Julian Anastasov   ipvs: optimize ds...
966
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967

4115ded13   Julian Anastasov   ipvs: consolidate...
968
  	rt = skb_rtable(skb);
d8d1f30b9   Changli Gao   net-next: remove ...
969
  	tdev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970

1da177e4c   Linus Torvalds   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   Alex Gartrell   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   Linus Torvalds   Linux-2.6.12-rc2
982

aed069df0   Alexander Duyck   ip_tunnel_core: i...
983
  	if (iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET, cp->af)))
ea1d5d775   Julian Anastasov   ipvs: properly de...
984
985
986
  		goto tx_error;
  
  	skb->transport_header = skb->network_header;
e2d1bca7e   Arnaldo Carvalho de Melo   [SK_BUFF]: Use sk...
987
988
  	skb_push(skb, sizeof(struct iphdr));
  	skb_reset_network_header(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
  	/*
  	 *	Push down and install the IPIP header.
  	 */
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
993
  	iph			=	ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
996
  	iph->version		=	4;
  	iph->ihl		=	sizeof(struct iphdr)>>2;
  	iph->frag_off		=	df;
8052ba292   Alex Gartrell   ipvs: support ipv...
997
998
  	iph->protocol		=	next_protocol;
  	iph->tos		=	dsfield;
c92f5ca2e   Julian Anastasov   ipvs: Remove all ...
999
1000
  	iph->daddr		=	cp->daddr.ip;
  	iph->saddr		=	saddr;
8052ba292   Alex Gartrell   ipvs: support ipv...
1001
  	iph->ttl		=	ttl;
b6a7719ae   Hannes Frederic Sowa   ipv4: hash net pt...
1002
  	ip_select_ident(net, skb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
  
  	/* Another hack: avoid icmp_send in ip_fragment */
60ff74673   WANG Cong   net: rename local...
1005
  	skb->ignore_df = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006

b8abdf098   Julian Anastasov   ipvs: convert the...
1007
  	ret = ip_vs_tunnel_xmit_prepare(skb, cp);
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
1008
  	if (ret == NF_ACCEPT)
33224b16f   Eric W. Biederman   ipv4, ipv6: Pass ...
1009
  		ip_local_out(net, skb->sk, skb);
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
1010
1011
  	else if (ret == NF_DROP)
  		kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
1012
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
1014
1015
1016
  
  	LeaveFunction(10);
  
  	return NF_STOLEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
    tx_error:
ea1d5d775   Julian Anastasov   ipvs: properly de...
1018
1019
  	if (!IS_ERR(skb))
  		kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
1020
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
1022
1023
  	LeaveFunction(10);
  	return NF_STOLEN;
  }
b3cdd2a73   Julius Volz   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   Jesper Dangaard Brouer   ipvs: API change ...
1027
  		     struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1028
1029
  {
  	struct rt6_info *rt;		/* Route to the other host */
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
1030
  	struct in6_addr saddr;		/* Source for tunnel */
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1031
  	struct net_device *tdev;	/* Device to other host */
8052ba292   Alex Gartrell   ipvs: support ipv...
1032
1033
1034
1035
  	__u8 next_protocol = 0;
  	__u32 payload_len = 0;
  	__u8 dsfield = 0;
  	__u8 ttl = 0;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1036
1037
  	struct ipv6hdr  *iph;		/* Our new IP header */
  	unsigned int max_headroom;	/* The extra header space needed */
4115ded13   Julian Anastasov   ipvs: consolidate...
1038
  	int ret, local;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1039
1040
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
1041
  	rcu_read_lock();
f5745f8ae   Eric W. Biederman   ipvs: Pass ipvs i...
1042
1043
  	local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest,
  				      &cp->daddr.in6,
4115ded13   Julian Anastasov   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   Julian Anastasov   ipvs: optimize ds...
1050
1051
  	if (local) {
  		rcu_read_unlock();
b8abdf098   Julian Anastasov   ipvs: convert the...
1052
  		return ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 1);
026ace060   Julian Anastasov   ipvs: optimize ds...
1053
  	}
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1054

4115ded13   Julian Anastasov   ipvs: consolidate...
1055
  	rt = (struct rt6_info *) skb_dst(skb);
d8d1f30b9   Changli Gao   net-next: remove ...
1056
  	tdev = rt->dst.dev;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1057

b3cdd2a73   Julius Volz   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   Alex Gartrell   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   Julius Volz   IPVS: Add and bin...
1067

aed069df0   Alexander Duyck   ip_tunnel_core: i...
1068
  	if (iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET6, cp->af)))
ea1d5d775   Julian Anastasov   ipvs: properly de...
1069
  		goto tx_error;
714f095f7   Hans Schillstrom   ipvs: IPv6 tunnel...
1070
  	skb->transport_header = skb->network_header;
b3cdd2a73   Julius Volz   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   Julius Volz   IPVS: Add and bin...
1075
1076
1077
1078
1079
  	/*
  	 *	Push down and install the IPIP header.
  	 */
  	iph			=	ipv6_hdr(skb);
  	iph->version		=	6;
8052ba292   Alex Gartrell   ipvs: support ipv...
1080
1081
  	iph->nexthdr		=	next_protocol;
  	iph->payload_len	=	htons(payload_len);
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1082
  	memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
8052ba292   Alex Gartrell   ipvs: support ipv...
1083
  	ipv6_change_dsfield(iph, 0, dsfield);
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1084
1085
  	iph->daddr = cp->daddr.in6;
  	iph->saddr = saddr;
8052ba292   Alex Gartrell   ipvs: support ipv...
1086
  	iph->hop_limit		=	ttl;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1087
1088
  
  	/* Another hack: avoid icmp_send in ip_fragment */
60ff74673   WANG Cong   net: rename local...
1089
  	skb->ignore_df = 1;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1090

b8abdf098   Julian Anastasov   ipvs: convert the...
1091
  	ret = ip_vs_tunnel_xmit_prepare(skb, cp);
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
1092
  	if (ret == NF_ACCEPT)
33224b16f   Eric W. Biederman   ipv4, ipv6: Pass ...
1093
  		ip6_local_out(cp->ipvs->net, skb->sk, skb);
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
1094
1095
  	else if (ret == NF_DROP)
  		kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
1096
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1097
1098
1099
1100
  
  	LeaveFunction(10);
  
  	return NF_STOLEN;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1101
  tx_error:
ea1d5d775   Julian Anastasov   ipvs: properly de...
1102
1103
  	if (!IS_ERR(skb))
  		kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
1104
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1105
1106
1107
1108
  	LeaveFunction(10);
  	return NF_STOLEN;
  }
  #endif
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
1116
  	      struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1117
  {
4115ded13   Julian Anastasov   ipvs: consolidate...
1118
  	int local;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
1121
  	rcu_read_lock();
ecfe87b88   Eric W. Biederman   ipvs: Pass ipvs i...
1122
  	local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip,
4115ded13   Julian Anastasov   ipvs: consolidate...
1123
1124
  				   IP_VS_RT_MODE_LOCAL |
  				   IP_VS_RT_MODE_NON_LOCAL |
c63e4de2b   Alex Gartrell   ipvs: Add generic...
1125
  				   IP_VS_RT_MODE_KNOWN_NH, NULL, ipvsh);
4115ded13   Julian Anastasov   ipvs: consolidate...
1126
  	if (local < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
  		goto tx_error;
026ace060   Julian Anastasov   ipvs: optimize ds...
1128
1129
  	if (local) {
  		rcu_read_unlock();
4115ded13   Julian Anastasov   ipvs: consolidate...
1130
  		return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1);
026ace060   Julian Anastasov   ipvs: optimize ds...
1131
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132

eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1133
  	ip_send_check(ip_hdr(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
  	/* Another hack: avoid icmp_send in ip_fragment */
60ff74673   WANG Cong   net: rename local...
1136
  	skb->ignore_df = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137

b8abdf098   Julian Anastasov   ipvs: convert the...
1138
  	ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 0);
026ace060   Julian Anastasov   ipvs: optimize ds...
1139
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140
1141
1142
  
  	LeaveFunction(10);
  	return NF_STOLEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
    tx_error:
  	kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
1145
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
1147
1148
  	LeaveFunction(10);
  	return NF_STOLEN;
  }
b3cdd2a73   Julius Volz   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   Julian Anastasov   ipvs: consolidate...
1152
  		 struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1153
  {
4115ded13   Julian Anastasov   ipvs: consolidate...
1154
  	int local;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1155
1156
  
  	EnterFunction(10);
026ace060   Julian Anastasov   ipvs: optimize ds...
1157
  	rcu_read_lock();
f5745f8ae   Eric W. Biederman   ipvs: Pass ipvs i...
1158
1159
  	local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest,
  				      &cp->daddr.in6,
4a4739d56   Alex Gartrell   ipvs: Pull out cr...
1160
  				      NULL, ipvsh, 0,
4115ded13   Julian Anastasov   ipvs: consolidate...
1161
  				      IP_VS_RT_MODE_LOCAL |
48e8aa6e3   Martin KaFai Lau   ipv6: Set FLOWI_F...
1162
1163
  				      IP_VS_RT_MODE_NON_LOCAL |
  				      IP_VS_RT_MODE_KNOWN_NH);
4115ded13   Julian Anastasov   ipvs: consolidate...
1164
  	if (local < 0)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1165
  		goto tx_error;
026ace060   Julian Anastasov   ipvs: optimize ds...
1166
1167
  	if (local) {
  		rcu_read_unlock();
4115ded13   Julian Anastasov   ipvs: consolidate...
1168
  		return ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 1);
026ace060   Julian Anastasov   ipvs: optimize ds...
1169
  	}
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1170
1171
  
  	/* Another hack: avoid icmp_send in ip_fragment */
60ff74673   WANG Cong   net: rename local...
1172
  	skb->ignore_df = 1;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1173

b8abdf098   Julian Anastasov   ipvs: convert the...
1174
  	ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 0);
026ace060   Julian Anastasov   ipvs: optimize ds...
1175
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1176
1177
1178
  
  	LeaveFunction(10);
  	return NF_STOLEN;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1179
1180
  tx_error:
  	kfree_skb(skb);
026ace060   Julian Anastasov   ipvs: optimize ds...
1181
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1182
1183
1184
1185
  	LeaveFunction(10);
  	return NF_STOLEN;
  }
  #endif
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
1193
1194
  		struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
  		struct ip_vs_iphdr *iph)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
  {
  	struct rtable	*rt;	/* Route to the other host */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
  	int rc;
fc6047676   Julian Anastasov   ipvs: changes for...
1198
  	int local;
4115ded13   Julian Anastasov   ipvs: consolidate...
1199
  	int rt_mode, was_input;
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   ipvs: API change ...
1208
  			rc = cp->packet_xmit(skb, cp, pp, iph);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
1210
1211
1212
  		else
  			rc = NF_ACCEPT;
  		/* do not touch skb anymore */
  		atomic_inc(&cp->in_pkts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
1215
1216
1217
1218
  		goto out;
  	}
  
  	/*
  	 * mangle and send the packet here (only for VS/NAT)
  	 */
4115ded13   Julian Anastasov   ipvs: consolidate...
1219
  	was_input = rt_is_input_route(skb_rtable(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220

c92f5ca2e   Julian Anastasov   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   Julian Anastasov   ipvs: optimize ds...
1225
  	rcu_read_lock();
ecfe87b88   Eric W. Biederman   ipvs: Pass ipvs i...
1226
  	local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, rt_mode,
c63e4de2b   Alex Gartrell   ipvs: Add generic...
1227
  				   NULL, iph);
4115ded13   Julian Anastasov   ipvs: consolidate...
1228
1229
1230
  	if (local < 0)
  		goto tx_error;
  	rt = skb_rtable(skb);
fc6047676   Julian Anastasov   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   Igor Maravić   net:netfilter: us...
1236
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
fc6047676   Julian Anastasov   ipvs: changes for...
1237
1238
  	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
  		enum ip_conntrack_info ctinfo;
05b4b065a   Alan Cox   ipvs: remove sill...
1239
  		struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
fc6047676   Julian Anastasov   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   Julian Anastasov   ipvs: consolidate...
1246
  			goto tx_error;
fc6047676   Julian Anastasov   ipvs: changes for...
1247
1248
1249
1250
1251
  		}
  	}
  #endif
  
  	/* From world but DNAT to loopback address? */
4115ded13   Julian Anastasov   ipvs: consolidate...
1252
  	if (local && ipv4_is_loopback(cp->daddr.ip) && was_input) {
fc6047676   Julian Anastasov   ipvs: changes for...
1253
1254
1255
1256
  		IP_VS_DBG(1, "%s(): "
  			  "stopping DNAT to loopback %pI4
  ",
  			  __func__, &cp->daddr.ip);
4115ded13   Julian Anastasov   ipvs: consolidate...
1257
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
1260
  	}
  
  	/* copy-on-write the packet before mangling it */
af1e1cf07   Herbert Xu   [IPVS]: Replace l...
1261
  	if (!skb_make_writable(skb, offset))
4115ded13   Julian Anastasov   ipvs: consolidate...
1262
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263

d8d1f30b9   Changli Gao   net-next: remove ...
1264
  	if (skb_cow(skb, rt->dst.dev->hard_header_len))
4115ded13   Julian Anastasov   ipvs: consolidate...
1265
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266

1da177e4c   Linus Torvalds   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   WANG Cong   net: rename local...
1270
  	skb->ignore_df = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271

b8abdf098   Julian Anastasov   ipvs: convert the...
1272
  	rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local);
026ace060   Julian Anastasov   ipvs: optimize ds...
1273
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1275
    tx_error:
026ace060   Julian Anastasov   ipvs: optimize ds...
1276
1277
  	kfree_skb(skb);
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
  	rc = NF_STOLEN;
    out:
  	LeaveFunction(10);
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
  }
b3cdd2a73   Julius Volz   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   Jesper Dangaard Brouer   ipvs: API change ...
1287
  		struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
4115ded13   Julian Anastasov   ipvs: consolidate...
1288
  		struct ip_vs_iphdr *ipvsh)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1289
1290
  {
  	struct rt6_info	*rt;	/* Route to the other host */
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1291
  	int rc;
fc6047676   Julian Anastasov   ipvs: changes for...
1292
  	int local;
c92f5ca2e   Julian Anastasov   ipvs: Remove all ...
1293
  	int rt_mode;
b3cdd2a73   Julius Volz   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   Julian Anastasov   ipvs: consolidate...
1302
  			rc = cp->packet_xmit(skb, cp, pp, ipvsh);
b3cdd2a73   Julius Volz   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   Julian Anastasov   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   Julian Anastasov   ipvs: optimize ds...
1317
  	rcu_read_lock();
f5745f8ae   Eric W. Biederman   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   Julian Anastasov   ipvs: consolidate...
1320
1321
1322
  	if (local < 0)
  		goto tx_error;
  	rt = (struct rt6_info *) skb_dst(skb);
fc6047676   Julian Anastasov   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   Igor Maravić   net:netfilter: us...
1327
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
fc6047676   Julian Anastasov   ipvs: changes for...
1328
1329
  	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
  		enum ip_conntrack_info ctinfo;
05b4b065a   Alan Cox   ipvs: remove sill...
1330
  		struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
fc6047676   Julian Anastasov   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   Julian Anastasov   ipvs: consolidate...
1337
  			goto tx_error;
fc6047676   Julian Anastasov   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   Martin KaFai Lau   ipv6: Remove exte...
1344
  	    ipv6_addr_type(&cp->daddr.in6) & IPV6_ADDR_LOOPBACK) {
fc6047676   Julian Anastasov   ipvs: changes for...
1345
1346
1347
1348
  		IP_VS_DBG(1, "%s(): "
  			  "stopping DNAT to loopback %pI6
  ",
  			  __func__, &cp->daddr.in6);
4115ded13   Julian Anastasov   ipvs: consolidate...
1349
  		goto tx_error;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1350
1351
1352
1353
  	}
  
  	/* copy-on-write the packet before mangling it */
  	if (!skb_make_writable(skb, offset))
4115ded13   Julian Anastasov   ipvs: consolidate...
1354
  		goto tx_error;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1355

d8d1f30b9   Changli Gao   net-next: remove ...
1356
  	if (skb_cow(skb, rt->dst.dev->hard_header_len))
4115ded13   Julian Anastasov   ipvs: consolidate...
1357
  		goto tx_error;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1358

b3cdd2a73   Julius Volz   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   WANG Cong   net: rename local...
1362
  	skb->ignore_df = 1;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1363

b8abdf098   Julian Anastasov   ipvs: convert the...
1364
  	rc = ip_vs_nat_send_or_cont(NFPROTO_IPV6, skb, cp, local);
026ace060   Julian Anastasov   ipvs: optimize ds...
1365
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1366
  	goto out;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1367
  tx_error:
026ace060   Julian Anastasov   ipvs: optimize ds...
1368
1369
  	kfree_skb(skb);
  	rcu_read_unlock();
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1370
1371
1372
1373
  	rc = NF_STOLEN;
  out:
  	LeaveFunction(10);
  	return rc;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
1374
1375
  }
  #endif