aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c77
1 files changed, 51 insertions, 26 deletions
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 034a282a6f8c..fa2fdd7421b7 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -213,17 +213,57 @@ static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu)
213 ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu); 213 ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu);
214} 214}
215 215
216static inline bool ensure_mtu_is_adequate(int skb_af, int rt_mode,
217 struct ip_vs_iphdr *ipvsh,
218 struct sk_buff *skb, int mtu)
219{
220#ifdef CONFIG_IP_VS_IPV6
221 if (skb_af == AF_INET6) {
222 struct net *net = dev_net(skb_dst(skb)->dev);
223
224 if (unlikely(__mtu_check_toobig_v6(skb, mtu))) {
225 if (!skb->dev)
226 skb->dev = net->loopback_dev;
227 /* only send ICMP too big on first fragment */
228 if (!ipvsh->fragoffs)
229 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
230 IP_VS_DBG(1, "frag needed for %pI6c\n",
231 &ipv6_hdr(skb)->saddr);
232 return false;
233 }
234 } else
235#endif
236 {
237 struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
238
239 /* If we're going to tunnel the packet and pmtu discovery
240 * is disabled, we'll just fragment it anyway
241 */
242 if ((rt_mode & IP_VS_RT_MODE_TUNNEL) && !sysctl_pmtu_disc(ipvs))
243 return true;
244
245 if (unlikely(ip_hdr(skb)->frag_off & htons(IP_DF) &&
246 skb->len > mtu && !skb_is_gso(skb))) {
247 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
248 htonl(mtu));
249 IP_VS_DBG(1, "frag needed for %pI4\n",
250 &ip_hdr(skb)->saddr);
251 return false;
252 }
253 }
254
255 return true;
256}
257
216/* Get route to destination or remote server */ 258/* Get route to destination or remote server */
217static int 259static int
218__ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, 260__ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
219 __be32 daddr, int rt_mode, __be32 *ret_saddr) 261 __be32 daddr, int rt_mode, __be32 *ret_saddr,
262 struct ip_vs_iphdr *ipvsh)
220{ 263{
221 struct net *net = dev_net(skb_dst(skb)->dev); 264 struct net *net = dev_net(skb_dst(skb)->dev);
222 struct netns_ipvs *ipvs = net_ipvs(net);
223 struct ip_vs_dest_dst *dest_dst; 265 struct ip_vs_dest_dst *dest_dst;
224 struct rtable *rt; /* Route to the other host */ 266 struct rtable *rt; /* Route to the other host */
225 struct iphdr *iph;
226 __be16 df;
227 int mtu; 267 int mtu;
228 int local, noref = 1; 268 int local, noref = 1;
229 269
@@ -279,7 +319,6 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
279 " daddr=%pI4\n", &dest->addr.ip); 319 " daddr=%pI4\n", &dest->addr.ip);
280 goto err_put; 320 goto err_put;
281 } 321 }
282 iph = ip_hdr(skb);
283 322
284 if (unlikely(local)) { 323 if (unlikely(local)) {
285 /* skb to local stack, preserve old route */ 324 /* skb to local stack, preserve old route */
@@ -290,7 +329,6 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
290 329
291 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) { 330 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
292 mtu = dst_mtu(&rt->dst); 331 mtu = dst_mtu(&rt->dst);
293 df = iph->frag_off & htons(IP_DF);
294 } else { 332 } else {
295 mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); 333 mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
296 if (mtu < 68) { 334 if (mtu < 68) {
@@ -298,16 +336,10 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
298 goto err_put; 336 goto err_put;
299 } 337 }
300 maybe_update_pmtu(skb_af, skb, mtu); 338 maybe_update_pmtu(skb_af, skb, mtu);
301 /* MTU check allowed? */
302 df = sysctl_pmtu_disc(ipvs) ? iph->frag_off & htons(IP_DF) : 0;
303 } 339 }
304 340
305 /* MTU checking */ 341 if (!ensure_mtu_is_adequate(skb_af, rt_mode, ipvsh, skb, mtu))
306 if (unlikely(df && skb->len > mtu && !skb_is_gso(skb))) {
307 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
308 IP_VS_DBG(1, "frag needed for %pI4\n", &iph->saddr);
309 goto err_put; 342 goto err_put;
310 }
311 343
312 skb_dst_drop(skb); 344 skb_dst_drop(skb);
313 if (noref) { 345 if (noref) {
@@ -450,15 +482,8 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
450 maybe_update_pmtu(skb_af, skb, mtu); 482 maybe_update_pmtu(skb_af, skb, mtu);
451 } 483 }
452 484
453 if (unlikely(__mtu_check_toobig_v6(skb, mtu))) { 485 if (!ensure_mtu_is_adequate(skb_af, rt_mode, ipvsh, skb, mtu))
454 if (!skb->dev)
455 skb->dev = net->loopback_dev;
456 /* only send ICMP too big on first fragment */
457 if (!ipvsh->fragoffs)
458 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
459 IP_VS_DBG(1, "frag needed for %pI6c\n", &ipv6_hdr(skb)->saddr);
460 goto err_put; 486 goto err_put;
461 }
462 487
463 skb_dst_drop(skb); 488 skb_dst_drop(skb);
464 if (noref) { 489 if (noref) {
@@ -565,7 +590,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
565 590
566 rcu_read_lock(); 591 rcu_read_lock();
567 if (__ip_vs_get_out_rt(cp->af, skb, NULL, iph->daddr, 592 if (__ip_vs_get_out_rt(cp->af, skb, NULL, iph->daddr,
568 IP_VS_RT_MODE_NON_LOCAL, NULL) < 0) 593 IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh) < 0)
569 goto tx_error; 594 goto tx_error;
570 595
571 ip_send_check(iph); 596 ip_send_check(iph);
@@ -644,7 +669,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
644 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip, 669 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip,
645 IP_VS_RT_MODE_LOCAL | 670 IP_VS_RT_MODE_LOCAL |
646 IP_VS_RT_MODE_NON_LOCAL | 671 IP_VS_RT_MODE_NON_LOCAL |
647 IP_VS_RT_MODE_RDR, NULL); 672 IP_VS_RT_MODE_RDR, NULL, ipvsh);
648 if (local < 0) 673 if (local < 0)
649 goto tx_error; 674 goto tx_error;
650 rt = skb_rtable(skb); 675 rt = skb_rtable(skb);
@@ -841,7 +866,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
841 IP_VS_RT_MODE_LOCAL | 866 IP_VS_RT_MODE_LOCAL |
842 IP_VS_RT_MODE_NON_LOCAL | 867 IP_VS_RT_MODE_NON_LOCAL |
843 IP_VS_RT_MODE_CONNECT | 868 IP_VS_RT_MODE_CONNECT |
844 IP_VS_RT_MODE_TUNNEL, &saddr); 869 IP_VS_RT_MODE_TUNNEL, &saddr, ipvsh);
845 if (local < 0) 870 if (local < 0)
846 goto tx_error; 871 goto tx_error;
847 if (local) { 872 if (local) {
@@ -1032,7 +1057,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1032 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip, 1057 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip,
1033 IP_VS_RT_MODE_LOCAL | 1058 IP_VS_RT_MODE_LOCAL |
1034 IP_VS_RT_MODE_NON_LOCAL | 1059 IP_VS_RT_MODE_NON_LOCAL |
1035 IP_VS_RT_MODE_KNOWN_NH, NULL); 1060 IP_VS_RT_MODE_KNOWN_NH, NULL, ipvsh);
1036 if (local < 0) 1061 if (local < 0)
1037 goto tx_error; 1062 goto tx_error;
1038 if (local) { 1063 if (local) {
@@ -1137,7 +1162,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1137 IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; 1162 IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
1138 rcu_read_lock(); 1163 rcu_read_lock();
1139 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip, rt_mode, 1164 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip, rt_mode,
1140 NULL); 1165 NULL, iph);
1141 if (local < 0) 1166 if (local < 0)
1142 goto tx_error; 1167 goto tx_error;
1143 rt = skb_rtable(skb); 1168 rt = skb_rtable(skb);