ipv6: add option to drop unsolicited neighbor advertisements
authorJohannes Berg <johannes.berg@intel.com>
Thu, 4 Feb 2016 12:31:20 +0000 (13:31 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Feb 2016 09:27:36 +0000 (04:27 -0500)
In certain 802.11 wireless deployments, there will be NA proxies
that use knowledge of the network to correctly answer requests.
To prevent unsolicitd advertisements on the shared medium from
being a problem, on such deployments wireless needs to drop them.

Enable this by providing an option called "drop_unsolicited_na".

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/ip-sysctl.txt
include/linux/ipv6.h
include/uapi/linux/ipv6.h
net/ipv6/addrconf.c
net/ipv6/ndisc.c

index e0e7350a4e6a9b37f49bac6db0e3332d27bb7ecd..24ce97f42d3552cc8ddd9a1de0855a1acb9bdf06 100644 (file)
@@ -1680,6 +1680,13 @@ drop_unicast_in_l2_multicast - BOOLEAN
 
        By default this is turned off.
 
+drop_unsolicited_na - BOOLEAN
+       Drop all unsolicited neighbor advertisements, for example if there's
+       a known good NA proxy on the network and such frames need not be used
+       (or in the case of 802.11, must not be used to prevent attacks.)
+
+       By default this is turned off.
+
 icmp/*:
 ratelimit - INTEGER
        Limit the maximal rates for sending ICMPv6 packets.
index 4a4c1ae826cbcbea916e62a575b959014329de0e..4b2267e1b7c3300487b0dffab84326d259fb3822 100644 (file)
@@ -56,6 +56,7 @@ struct ipv6_devconf {
        __s32           ndisc_notify;
        __s32           suppress_frag_ndisc;
        __s32           accept_ra_mtu;
+       __s32           drop_unsolicited_na;
        struct ipv6_stable_secret {
                bool initialized;
                struct in6_addr secret;
index 4c413570efe8ddfafc30c40e3f1c429f421aeb08..ec117b65d5a519c7c524b03b20a7522a6b1e1113 100644 (file)
@@ -175,6 +175,7 @@ enum {
        DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
        DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN,
        DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
+       DEVCONF_DROP_UNSOLICITED_NA,
        DEVCONF_MAX
 };
 
index 23e325f39f8e99d5e9f6ba16c13ee2ee3e2eef97..ac0ba9e4e06b95769b7471ddfa8805e61a61f9c5 100644 (file)
@@ -4712,6 +4712,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        /* we omit DEVCONF_STABLE_SECRET for now */
        array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only;
        array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast;
+       array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -5792,6 +5793,13 @@ static struct addrconf_sysctl_table
                        .mode           = 0644,
                        .proc_handler   = proc_dointvec,
                },
+               {
+                       .procname       = "drop_unsolicited_na",
+                       .data           = &ipv6_devconf.drop_unsolicited_na,
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = proc_dointvec,
+               },
                {
                        /* sentinel */
                }
index 84afb9a7727848038b51ee7a60eebb28d555f693..c245895a3d416b3eed0ab537b61950b618b2944c 100644 (file)
@@ -883,6 +883,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
                                    offsetof(struct nd_msg, opt));
        struct ndisc_options ndopts;
        struct net_device *dev = skb->dev;
+       struct inet6_dev *idev = __in6_dev_get(dev);
        struct inet6_ifaddr *ifp;
        struct neighbour *neigh;
 
@@ -902,6 +903,14 @@ static void ndisc_recv_na(struct sk_buff *skb)
                return;
        }
 
+       /* For some 802.11 wireless deployments (and possibly other networks),
+        * there will be a NA proxy and unsolicitd packets are attacks
+        * and thus should not be accepted.
+        */
+       if (!msg->icmph.icmp6_solicited && idev &&
+           idev->cnf.drop_unsolicited_na)
+               return;
+
        if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
                ND_PRINTK(2, warn, "NS: invalid ND option\n");
                return;