@@ -119,6 +119,7 @@ static void ipv6_regen_rndid(unsigned long data);
119119static int desync_factor = MAX_DESYNC_FACTOR * HZ ;
120120#endif
121121
122+ static int ipv6_generate_eui64 (u8 * eui , struct net_device * dev );
122123static int ipv6_count_addresses (struct inet6_dev * idev );
123124
124125/*
@@ -183,6 +184,8 @@ struct ipv6_devconf ipv6_devconf __read_mostly = {
183184#endif
184185 .proxy_ndp = 0 ,
185186 .accept_source_route = 0 , /* we do not accept RH0 by default. */
187+ .disable_ipv6 = 0 ,
188+ .accept_dad = 1 ,
186189};
187190
188191static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -215,6 +218,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
215218#endif
216219 .proxy_ndp = 0 ,
217220 .accept_source_route = 0 , /* we do not accept RH0 by default. */
221+ .disable_ipv6 = 0 ,
222+ .accept_dad = 1 ,
218223};
219224
220225/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -378,6 +383,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
378383 */
379384 in6_dev_hold (ndev );
380385
386+ if (dev -> flags & (IFF_NOARP | IFF_LOOPBACK ))
387+ ndev -> cnf .accept_dad = -1 ;
388+
381389#if defined(CONFIG_IPV6_SIT ) || defined(CONFIG_IPV6_SIT_MODULE )
382390 if (dev -> type == ARPHRD_SIT && (dev -> priv_flags & IFF_ISATAP )) {
383391 printk (KERN_INFO
@@ -578,6 +586,13 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
578586 struct rt6_info * rt ;
579587 int hash ;
580588 int err = 0 ;
589+ int addr_type = ipv6_addr_type (addr );
590+
591+ if (addr_type == IPV6_ADDR_ANY ||
592+ addr_type & IPV6_ADDR_MULTICAST ||
593+ (!(idev -> dev -> flags & IFF_LOOPBACK ) &&
594+ addr_type & IPV6_ADDR_LOOPBACK ))
595+ return ERR_PTR (- EADDRNOTAVAIL );
581596
582597 rcu_read_lock_bh ();
583598 if (idev -> dead ) {
@@ -1412,6 +1427,20 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
14121427
14131428void addrconf_dad_failure (struct inet6_ifaddr * ifp )
14141429{
1430+ struct inet6_dev * idev = ifp -> idev ;
1431+ if (idev -> cnf .accept_dad > 1 && !idev -> cnf .disable_ipv6 ) {
1432+ struct in6_addr addr ;
1433+
1434+ addr .s6_addr32 [0 ] = htonl (0xfe800000 );
1435+ addr .s6_addr32 [1 ] = 0 ;
1436+
1437+ if (!ipv6_generate_eui64 (addr .s6_addr + 8 , idev -> dev ) &&
1438+ ipv6_addr_equal (& ifp -> addr , & addr )) {
1439+ /* DAD failed for link-local based on MAC address */
1440+ idev -> cnf .disable_ipv6 = 1 ;
1441+ }
1442+ }
1443+
14151444 if (net_ratelimit ())
14161445 printk (KERN_INFO "%s: duplicate address detected!\n" , ifp -> idev -> dev -> name );
14171446 addrconf_dad_stop (ifp );
@@ -2744,6 +2773,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
27442773 spin_lock_bh (& ifp -> lock );
27452774
27462775 if (dev -> flags & (IFF_NOARP |IFF_LOOPBACK ) ||
2776+ idev -> cnf .accept_dad < 1 ||
27472777 !(ifp -> flags & IFA_F_TENTATIVE ) ||
27482778 ifp -> flags & IFA_F_NODAD ) {
27492779 ifp -> flags &= ~(IFA_F_TENTATIVE |IFA_F_OPTIMISTIC );
@@ -2791,6 +2821,11 @@ static void addrconf_dad_timer(unsigned long data)
27912821 read_unlock_bh (& idev -> lock );
27922822 goto out ;
27932823 }
2824+ if (idev -> cnf .accept_dad > 1 && idev -> cnf .disable_ipv6 ) {
2825+ read_unlock_bh (& idev -> lock );
2826+ addrconf_dad_failure (ifp );
2827+ return ;
2828+ }
27942829 spin_lock_bh (& ifp -> lock );
27952830 if (ifp -> probes == 0 ) {
27962831 /*
@@ -3650,6 +3685,8 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
36503685#ifdef CONFIG_IPV6_MROUTE
36513686 array [DEVCONF_MC_FORWARDING ] = cnf -> mc_forwarding ;
36523687#endif
3688+ array [DEVCONF_DISABLE_IPV6 ] = cnf -> disable_ipv6 ;
3689+ array [DEVCONF_ACCEPT_DAD ] = cnf -> accept_dad ;
36533690}
36543691
36553692static inline size_t inet6_if_nlmsg_size (void )
@@ -4208,6 +4245,22 @@ static struct addrconf_sysctl_table
42084245 .proc_handler = & proc_dointvec ,
42094246 },
42104247#endif
4248+ {
4249+ .ctl_name = CTL_UNNUMBERED ,
4250+ .procname = "disable_ipv6" ,
4251+ .data = & ipv6_devconf .disable_ipv6 ,
4252+ .maxlen = sizeof (int ),
4253+ .mode = 0644 ,
4254+ .proc_handler = & proc_dointvec ,
4255+ },
4256+ {
4257+ .ctl_name = CTL_UNNUMBERED ,
4258+ .procname = "accept_dad" ,
4259+ .data = & ipv6_devconf .accept_dad ,
4260+ .maxlen = sizeof (int ),
4261+ .mode = 0644 ,
4262+ .proc_handler = & proc_dointvec ,
4263+ },
42114264 {
42124265 .ctl_name = 0 , /* sentinel */
42134266 }
0 commit comments