aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt7
-rw-r--r--include/net/ip6_route.h7
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/sysctl_net_ipv6.c8
5 files changed, 26 insertions, 1 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index d71afa8bd828..7373115407e4 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1094,6 +1094,13 @@ bindv6only - BOOLEAN
1094 1094
1095 Default: FALSE (as specified in RFC3493) 1095 Default: FALSE (as specified in RFC3493)
1096 1096
1097anycast_src_echo_reply - BOOLEAN
1098 Controls the use of anycast addresses as source addresses for ICMPv6
1099 echo reply
1100 TRUE: enabled
1101 FALSE: disabled
1102 Default: FALSE
1103
1097IPv6 Fragmentation: 1104IPv6 Fragmentation:
1098 1105
1099ip6frag_high_thresh - INTEGER 1106ip6frag_high_thresh - INTEGER
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 1fb6cddbd448..017badb1aec7 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -152,6 +152,13 @@ static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
152 return rt->rt6i_flags & RTF_LOCAL; 152 return rt->rt6i_flags & RTF_LOCAL;
153} 153}
154 154
155static inline bool ipv6_anycast_destination(const struct sk_buff *skb)
156{
157 struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
158
159 return rt->rt6i_flags & RTF_ANYCAST;
160}
161
155int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); 162int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
156 163
157static inline int ip6_skb_dst_mtu(struct sk_buff *skb) 164static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 0fb2401197c5..76fc7d1dbfd3 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -73,6 +73,7 @@ struct netns_ipv6 {
73#endif 73#endif
74 atomic_t dev_addr_genid; 74 atomic_t dev_addr_genid;
75 atomic_t rt_genid; 75 atomic_t rt_genid;
76 int anycast_src_echo_reply;
76}; 77};
77 78
78#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) 79#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 5d420095190f..9a809a4b3d86 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -556,7 +556,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
556 556
557 saddr = &ipv6_hdr(skb)->daddr; 557 saddr = &ipv6_hdr(skb)->daddr;
558 558
559 if (!ipv6_unicast_destination(skb)) 559 if (!ipv6_unicast_destination(skb) &&
560 !(net->ipv6.anycast_src_echo_reply &&
561 ipv6_anycast_destination(skb)))
560 saddr = NULL; 562 saddr = NULL;
561 563
562 memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); 564 memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 107b2f1d90ae..6b6a2c83027e 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -24,6 +24,13 @@ static struct ctl_table ipv6_table_template[] = {
24 .mode = 0644, 24 .mode = 0644,
25 .proc_handler = proc_dointvec 25 .proc_handler = proc_dointvec
26 }, 26 },
27 {
28 .procname = "anycast_src_echo_reply",
29 .data = &init_net.ipv6.anycast_src_echo_reply,
30 .maxlen = sizeof(int),
31 .mode = 0644,
32 .proc_handler = proc_dointvec
33 },
27 { } 34 { }
28}; 35};
29 36
@@ -51,6 +58,7 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
51 if (!ipv6_table) 58 if (!ipv6_table)
52 goto out; 59 goto out;
53 ipv6_table[0].data = &net->ipv6.sysctl.bindv6only; 60 ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
61 ipv6_table[1].data = &net->ipv6.anycast_src_echo_reply;
54 62
55 ipv6_route_table = ipv6_route_sysctl_init(net); 63 ipv6_route_table = ipv6_route_sysctl_init(net);
56 if (!ipv6_route_table) 64 if (!ipv6_route_table)