IPv6: add the option to use anycast addresses as source addresses in echo reply
authorFX Le Bail <fx.lebail@yahoo.com>
Tue, 7 Jan 2014 13:57:27 +0000 (14:57 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Jan 2014 20:51:39 +0000 (15:51 -0500)
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>
Documentation/networking/ip-sysctl.txt
include/net/ip6_route.h
include/net/netns/ipv6.h
net/ipv6/icmp.c
net/ipv6/sysctl_net_ipv6.c

index d71afa8bd82810d46e1e91f6275d8e2de3260176..7373115407e489592d4717f814866c5c531e62fa 100644 (file)
@@ -1094,6 +1094,13 @@ bindv6only - BOOLEAN
 
        Default: FALSE (as specified in RFC3493)
 
+anycast_src_echo_reply - BOOLEAN
+       Controls the use of anycast addresses as source addresses for ICMPv6
+       echo reply
+       TRUE:  enabled
+       FALSE: disabled
+       Default: FALSE
+
 IPv6 Fragmentation:
 
 ip6frag_high_thresh - INTEGER
index 1fb6cddbd4484669aaca8b8842e2e484de4d7d85..017badb1aec7e8648a6f71d473862b730a78b4e8 100644 (file)
@@ -152,6 +152,13 @@ static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
        return rt->rt6i_flags & RTF_LOCAL;
 }
 
+static inline bool ipv6_anycast_destination(const struct sk_buff *skb)
+{
+       struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
+
+       return rt->rt6i_flags & RTF_ANYCAST;
+}
+
 int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 
 static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
index 0fb2401197c51ecf9dd041066975cf5f0bb6a264..76fc7d1dbfd3a4f425a0afe0e88f40353b1468ea 100644 (file)
@@ -73,6 +73,7 @@ struct netns_ipv6 {
 #endif
        atomic_t                dev_addr_genid;
        atomic_t                rt_genid;
+       int                     anycast_src_echo_reply;
 };
 
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
index 5d420095190f20b32369428e8ca1f43b906a7fbf..9a809a4b3d862444ff858f92a4d87ad6662e3d15 100644 (file)
@@ -556,7 +556,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 
        saddr = &ipv6_hdr(skb)->daddr;
 
-       if (!ipv6_unicast_destination(skb))
+       if (!ipv6_unicast_destination(skb) &&
+           !(net->ipv6.anycast_src_echo_reply &&
+             ipv6_anycast_destination(skb)))
                saddr = NULL;
 
        memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
index 107b2f1d90ae8ff5e092c8306215c21f82350314..6b6a2c83027eaa810936e14178d8db1cdb06c531 100644 (file)
@@ -24,6 +24,13 @@ static struct ctl_table ipv6_table_template[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
+       {
+               .procname       = "anycast_src_echo_reply",
+               .data           = &init_net.ipv6.anycast_src_echo_reply,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
        { }
 };
 
@@ -51,6 +58,7 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
        if (!ipv6_table)
                goto out;
        ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
+       ipv6_table[1].data = &net->ipv6.anycast_src_echo_reply;
 
        ipv6_route_table = ipv6_route_sysctl_init(net);
        if (!ipv6_route_table)