[IPV6]: ROUTE: Add router_probe_interval sysctl.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv6 / addrconf.c
index d328d59861438ae0b8bad815a3ef34cacf7de328..e7add61e6e395896043f9ab413aa78e89578f184 100644 (file)
@@ -78,8 +78,6 @@
 
 #ifdef CONFIG_IPV6_PRIVACY
 #include <linux/random.h>
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
 #endif
 
 #include <asm/uaccess.h>
@@ -110,8 +108,6 @@ static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpad
 static void ipv6_regen_rndid(unsigned long data);
 
 static int desync_factor = MAX_DESYNC_FACTOR * HZ;
-static struct crypto_tfm *md5_tfm;
-static DEFINE_SPINLOCK(md5_tfm_lock);
 #endif
 
 static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -169,6 +165,12 @@ struct ipv6_devconf ipv6_devconf = {
        .max_desync_factor      = MAX_DESYNC_FACTOR,
 #endif
        .max_addresses          = IPV6_MAX_ADDRESSES,
+       .accept_ra_defrtr       = 1,
+       .accept_ra_pinfo        = 1,
+#ifdef CONFIG_IPV6_ROUTER_PREF
+       .accept_ra_rtr_pref     = 1,
+       .rtr_probe_interval     = 60 * HZ,
+#endif
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt = {
@@ -190,6 +192,12 @@ static struct ipv6_devconf ipv6_devconf_dflt = {
        .max_desync_factor      = MAX_DESYNC_FACTOR,
 #endif
        .max_addresses          = IPV6_MAX_ADDRESSES,
+       .accept_ra_defrtr       = 1,
+       .accept_ra_pinfo        = 1,
+#ifdef CONFIG_IPV6_ROUTER_PREF
+       .accept_ra_rtr_pref     = 1,
+       .rtr_probe_interval     = 60 * HZ,
+#endif
 };
 
 /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -371,8 +379,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
                in6_dev_hold(ndev);
 
 #ifdef CONFIG_IPV6_PRIVACY
-               get_random_bytes(ndev->rndid, sizeof(ndev->rndid));
-               get_random_bytes(ndev->entropy, sizeof(ndev->entropy));
                init_timer(&ndev->regen_timer);
                ndev->regen_timer.function = ipv6_regen_rndid;
                ndev->regen_timer.data = (unsigned long) ndev;
@@ -822,7 +828,7 @@ struct ipv6_saddr_score {
        int             addr_type;
        unsigned int    attrs;
        int             matchlen;
-       unsigned int    scope;
+       int             scope;
        unsigned int    rule;
 };
 
@@ -1305,52 +1311,67 @@ static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
        __ipv6_dev_ac_dec(ifp->idev, &addr);
 }
 
+static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
+{
+       if (dev->addr_len != ETH_ALEN)
+               return -1;
+       memcpy(eui, dev->dev_addr, 3);
+       memcpy(eui + 5, dev->dev_addr + 3, 3);
+
+       /*
+        * The zSeries OSA network cards can be shared among various
+        * OS instances, but the OSA cards have only one MAC address.
+        * This leads to duplicate address conflicts in conjunction
+        * with IPv6 if more than one instance uses the same card.
+        *
+        * The driver for these cards can deliver a unique 16-bit
+        * identifier for each instance sharing the same card.  It is
+        * placed instead of 0xFFFE in the interface identifier.  The
+        * "u" bit of the interface identifier is not inverted in this
+        * case.  Hence the resulting interface identifier has local
+        * scope according to RFC2373.
+        */
+       if (dev->dev_id) {
+               eui[3] = (dev->dev_id >> 8) & 0xFF;
+               eui[4] = dev->dev_id & 0xFF;
+       } else {
+               eui[3] = 0xFF;
+               eui[4] = 0xFE;
+               eui[0] ^= 2;
+       }
+       return 0;
+}
+
+static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
+{
+       /* XXX: inherit EUI-64 from other interface -- yoshfuji */
+       if (dev->addr_len != ARCNET_ALEN)
+               return -1;
+       memset(eui, 0, 7);
+       eui[7] = *(u8*)dev->dev_addr;
+       return 0;
+}
+
+static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
+{
+       if (dev->addr_len != INFINIBAND_ALEN)
+               return -1;
+       memcpy(eui, dev->dev_addr + 12, 8);
+       eui[0] |= 2;
+       return 0;
+}
+
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
        switch (dev->type) {
        case ARPHRD_ETHER:
        case ARPHRD_FDDI:
        case ARPHRD_IEEE802_TR:
-               if (dev->addr_len != ETH_ALEN)
-                       return -1;
-               memcpy(eui, dev->dev_addr, 3);
-               memcpy(eui + 5, dev->dev_addr + 3, 3);
-
-               /*
-                * The zSeries OSA network cards can be shared among various
-                * OS instances, but the OSA cards have only one MAC address.
-                * This leads to duplicate address conflicts in conjunction
-                * with IPv6 if more than one instance uses the same card.
-                * 
-                * The driver for these cards can deliver a unique 16-bit
-                * identifier for each instance sharing the same card.  It is
-                * placed instead of 0xFFFE in the interface identifier.  The
-                * "u" bit of the interface identifier is not inverted in this
-                * case.  Hence the resulting interface identifier has local
-                * scope according to RFC2373.
-                */
-               if (dev->dev_id) {
-                       eui[3] = (dev->dev_id >> 8) & 0xFF;
-                       eui[4] = dev->dev_id & 0xFF;
-               } else {
-                       eui[3] = 0xFF;
-                       eui[4] = 0xFE;
-                       eui[0] ^= 2;
-               }
-               return 0;
+               return addrconf_ifid_eui48(eui, dev);
        case ARPHRD_ARCNET:
-               /* XXX: inherit EUI-64 from other interface -- yoshfuji */
-               if (dev->addr_len != ARCNET_ALEN)
-                       return -1;
-               memset(eui, 0, 7);
-               eui[7] = *(u8*)dev->dev_addr;
-               return 0;
+               return addrconf_ifid_arcnet(eui, dev);
        case ARPHRD_INFINIBAND:
-               if (dev->addr_len != INFINIBAND_ALEN)
-                       return -1;
-               memcpy(eui, dev->dev_addr + 12, 8);
-               eui[0] |= 2;
-               return 0;
+               return addrconf_ifid_infiniband(eui, dev);
        }
        return -1;
 }
@@ -1376,34 +1397,9 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
 /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
 static int __ipv6_regen_rndid(struct inet6_dev *idev)
 {
-       struct net_device *dev;
-       struct scatterlist sg[2];
-
-       sg_set_buf(&sg[0], idev->entropy, 8);
-       sg_set_buf(&sg[1], idev->work_eui64, 8);
-
-       dev = idev->dev;
-
-       if (ipv6_generate_eui64(idev->work_eui64, dev)) {
-               printk(KERN_INFO
-                       "__ipv6_regen_rndid(idev=%p): cannot get EUI64 identifier; use random bytes.\n",
-                       idev);
-               get_random_bytes(idev->work_eui64, sizeof(idev->work_eui64));
-       }
 regen:
-       spin_lock(&md5_tfm_lock);
-       if (unlikely(md5_tfm == NULL)) {
-               spin_unlock(&md5_tfm_lock);
-               return -1;
-       }
-       crypto_digest_init(md5_tfm);
-       crypto_digest_update(md5_tfm, sg, 2);
-       crypto_digest_final(md5_tfm, idev->work_digest);
-       spin_unlock(&md5_tfm_lock);
-
-       memcpy(idev->rndid, &idev->work_digest[0], 8);
+       get_random_bytes(idev->rndid, sizeof(idev->rndid));
        idev->rndid[0] &= ~0x02;
-       memcpy(idev->entropy, &idev->work_digest[8], 8);
 
        /*
         * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
@@ -2143,7 +2139,6 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
                return;
        }
        ip6_tnl_add_linklocal(idev);
-       addrconf_add_mroute(dev);
 }
 
 static int addrconf_notify(struct notifier_block *this, unsigned long event, 
@@ -2165,6 +2160,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                                        dev->name);
                                break;
                        }
+
+                       if (idev)
+                               idev->if_flags |= IF_READY;
                } else {
                        if (!netif_carrier_ok(dev)) {
                                /* device is still not ready. */
@@ -3130,6 +3128,12 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
 #endif
        array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
+       array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
+       array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
+#ifdef CONFIG_IPV6_ROUTER_PREF
+       array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
+       array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
+#endif
 }
 
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
@@ -3321,9 +3325,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
        switch (event) {
        case RTM_NEWADDR:
-               dst_hold(&ifp->rt->u.dst);
-               if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL))
-                       dst_release(&ifp->rt->u.dst);
+               ip6_ins_rt(ifp->rt, NULL, NULL, NULL);
                if (ifp->idev->cnf.forwarding)
                        addrconf_join_anycast(ifp);
                break;
@@ -3334,8 +3336,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                dst_hold(&ifp->rt->u.dst);
                if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
                        dst_free(&ifp->rt->u.dst);
-               else
-                       dst_release(&ifp->rt->u.dst);
                break;
        }
 }
@@ -3586,6 +3586,41 @@ static struct addrconf_sysctl_table
                        .mode           =       0644,
                        .proc_handler   =       &proc_dointvec,
                },
+               {
+                       .ctl_name       =       NET_IPV6_ACCEPT_RA_DEFRTR,
+                       .procname       =       "accept_ra_defrtr",
+                       .data           =       &ipv6_devconf.accept_ra_defrtr,
+                       .maxlen         =       sizeof(int),
+                       .mode           =       0644,
+                       .proc_handler   =       &proc_dointvec,
+               },
+               {
+                       .ctl_name       =       NET_IPV6_ACCEPT_RA_PINFO,
+                       .procname       =       "accept_ra_pinfo",
+                       .data           =       &ipv6_devconf.accept_ra_pinfo,
+                       .maxlen         =       sizeof(int),
+                       .mode           =       0644,
+                       .proc_handler   =       &proc_dointvec,
+               },
+#ifdef CONFIG_IPV6_ROUTER_PREF
+               {
+                       .ctl_name       =       NET_IPV6_ACCEPT_RA_RTR_PREF,
+                       .procname       =       "accept_ra_rtr_pref",
+                       .data           =       &ipv6_devconf.accept_ra_rtr_pref,
+                       .maxlen         =       sizeof(int),
+                       .mode           =       0644,
+                       .proc_handler   =       &proc_dointvec,
+               },
+               {
+                       .ctl_name       =       NET_IPV6_RTR_PROBE_INTERVAL,
+                       .procname       =       "router_probe_interval",
+                       .data           =       &ipv6_devconf.rtr_probe_interval,
+                       .maxlen         =       sizeof(int),
+                       .mode           =       0644,
+                       .proc_handler   =       &proc_dointvec_jiffies,
+                       .strategy       =       &sysctl_jiffies,
+               },
+#endif
                {
                        .ctl_name       =       0,      /* sentinel */
                }
@@ -3761,13 +3796,6 @@ int __init addrconf_init(void)
 
        register_netdevice_notifier(&ipv6_dev_notf);
 
-#ifdef CONFIG_IPV6_PRIVACY
-       md5_tfm = crypto_alloc_tfm("md5", 0);
-       if (unlikely(md5_tfm == NULL))
-               printk(KERN_WARNING
-                       "failed to load transform for md5\n");
-#endif
-
        addrconf_verify(0);
        rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
@@ -3830,11 +3858,6 @@ void __exit addrconf_cleanup(void)
 
        rtnl_unlock();
 
-#ifdef CONFIG_IPV6_PRIVACY
-       crypto_free_tfm(md5_tfm);
-       md5_tfm = NULL;
-#endif
-
 #ifdef CONFIG_PROC_FS
        proc_net_remove("if_inet6");
 #endif