aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFX Le Bail <fx.lebail@yahoo.com>2014-01-07 08:57:27 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-07 15:51:39 -0500
commit509aba3b0d366b7f16a9a2eebac1156b25f5f622 (patch)
tree703f6a9807c1cc5f2ae451831f4ffe7eb2861baf
parent9ba75fb0c4b92416b94640b5a043c323a457f14a (diff)
IPv6: add the option to use anycast addresses as source addresses in echo reply
This change allows to follow a recommandation of RFC4942. - Add "anycast_src_echo_reply" sysctl to control the use of anycast addresses as source addresses for ICMPv6 echo reply. This sysctl is false by default to preserve existing behavior. - Add inline check ipv6_anycast_destination(). - Use them in icmpv6_echo_reply(). Reference: RFC4942 - IPv6 Transition/Coexistence Security Considerations (http://tools.ietf.org/html/rfc4942#section-2.1.6) 2.1.6. Anycast Traffic Identification and Security [...] To avoid exposing knowledge about the internal structure of the network, it is recommended that anycast servers now take advantage of the ability to return responses with the anycast address as the source address if possible. Signed-off-by: Francois-Xavier Le Bail <fx.lebail@yahoo.com> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-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)