ipv6: sysctl to restrict candidate source addresses
authorErik Kline <ek@google.com>
Wed, 22 Jul 2015 07:38:25 +0000 (16:38 +0900)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 27 Oct 2015 08:28:21 +0000 (16:28 +0800)
Per RFC 6724, section 4, "Candidate Source Addresses":

    It is RECOMMENDED that the candidate source addresses be the set
    of unicast addresses assigned to the interface that will be used
    to send to the destination (the "outgoing" interface).

Add a sysctl to enable this behaviour.

Signed-off-by: Erik Kline <ek@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[Simplified back-port of net-next 3985e8a3611a93bb36789f65db862e5700aab65e]

Bug: 19470192
Bug: 21832279
Bug: 22464419
Change-Id: Ib74ef945dcabe64215064f15ee1660b6524d65ce
(cherry picked from commit 0633924e7776754ccb473d649e5fa9ee45617a46)

Documentation/networking/ip-sysctl.txt
include/linux/ipv6.h
include/uapi/linux/ipv6.h
net/ipv6/addrconf.c

index fbfc9e0d75e0d8011b8e2b097c9491b3d816cb59..b4ec119dd00af9866d8047e82a76b66b5f38597e 100644 (file)
@@ -1258,6 +1258,13 @@ router_solicitations - INTEGER
        routers are present.
        Default: 3
 
+use_oif_addrs_only - BOOLEAN
+       When enabled, the candidate source addresses for destinations
+       routed via this interface are restricted to the set of addresses
+       configured on this interface (vis. RFC 6724, section 4).
+
+       Default: false
+
 use_tempaddr - INTEGER
        Preference for Privacy Extensions (RFC3041).
          <= 0 : disable Privacy Extensions
index ebc6306661ebb5fe17956e4916fc41b2765fcbbc..c4a36ab46cd5e5e088d1fdf28f44193df7f9fc72 100644 (file)
@@ -50,6 +50,7 @@ struct ipv6_devconf {
        __s32           accept_dad;
        __s32           force_tllao;
        __s32           ndisc_notify;
+       __s32           use_oif_addrs_only;
        void            *sysctl;
 };
 
index e9d0f7efde3b8dbd41790360df37336e213c1531..15ac588853d1be6e0dc2866869428d3c18cbda30 100644 (file)
@@ -162,6 +162,7 @@ enum {
        DEVCONF_NDISC_NOTIFY,
        DEVCONF_ACCEPT_RA_RT_TABLE,
        DEVCONF_USE_OPTIMISTIC,
+       DEVCONF_USE_OIF_ADDRS_ONLY,
        DEVCONF_MAX
 };
 
index 69e8b50a45bd5f28b49216878a9f9af611e26bcc..3eb43633d29005ca3a93ffa89196d554e02fc5c0 100644 (file)
@@ -203,6 +203,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
        .accept_source_route    = 0,    /* we do not accept RH0 by default. */
        .disable_ipv6           = 0,
        .accept_dad             = 1,
+       .use_oif_addrs_only     = 0,
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -238,6 +239,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
        .accept_source_route    = 0,    /* we do not accept RH0 by default. */
        .disable_ipv6           = 0,
        .accept_dad             = 1,
+       .use_oif_addrs_only     = 0,
 };
 
 /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -1386,9 +1388,15 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
                 *    include addresses assigned to interfaces
                 *    belonging to the same site as the outgoing
                 *    interface.)
+                *  - "It is RECOMMENDED that the candidate source addresses
+                *    be the set of unicast addresses assigned to the
+                *    interface that will be used to send to the destination
+                *    (the 'outgoing' interface)." (RFC 6724)
                 */
+               idev = dst_dev ? __in6_dev_get(dst_dev) : NULL;
                if (((dst_type & IPV6_ADDR_MULTICAST) ||
-                    dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
+                    dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL ||
+                    (idev && idev->cnf.use_oif_addrs_only)) &&
                    dst.ifindex && dev->ifindex != dst.ifindex)
                        continue;
 
@@ -4284,6 +4292,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
        array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
        array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
+       array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -5056,6 +5065,14 @@ static struct addrconf_sysctl_table
                        .mode           = 0644,
                        .proc_handler   = proc_dointvec
                },
+               {
+                       .procname       = "use_oif_addrs_only",
+                       .data           = &ipv6_devconf.use_oif_addrs_only,
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = proc_dointvec,
+
+               },
                {
                        /* sentinel */
                }