aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/if_inet6.h1
-rw-r--r--net/ipv6/addrconf.c74
2 files changed, 65 insertions, 10 deletions
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index e97a9accb71d..d8234f9bd4c4 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -24,6 +24,7 @@
24#define IF_RA_MANAGED 0x40 24#define IF_RA_MANAGED 0x40
25#define IF_RA_RCVD 0x20 25#define IF_RA_RCVD 0x20
26#define IF_RS_SENT 0x10 26#define IF_RS_SENT 0x10
27#define IF_READY 0x80000000
27 28
28/* prefix flags */ 29/* prefix flags */
29#define IF_PREFIX_ONLINK 0x01 30#define IF_PREFIX_ONLINK 0x01
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4ea8cf7c0cc4..d012f6ac7040 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -388,6 +388,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
388 } 388 }
389#endif 389#endif
390 390
391 if (netif_carrier_ok(dev))
392 ndev->if_flags |= IF_READY;
393
391 write_lock_bh(&addrconf_lock); 394 write_lock_bh(&addrconf_lock);
392 dev->ip6_ptr = ndev; 395 dev->ip6_ptr = ndev;
393 write_unlock_bh(&addrconf_lock); 396 write_unlock_bh(&addrconf_lock);
@@ -1215,10 +1218,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
1215 1218
1216/* Gets referenced address, destroys ifaddr */ 1219/* Gets referenced address, destroys ifaddr */
1217 1220
1218void addrconf_dad_failure(struct inet6_ifaddr *ifp) 1221void addrconf_dad_stop(struct inet6_ifaddr *ifp)
1219{ 1222{
1220 if (net_ratelimit())
1221 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
1222 if (ifp->flags&IFA_F_PERMANENT) { 1223 if (ifp->flags&IFA_F_PERMANENT) {
1223 spin_lock_bh(&ifp->lock); 1224 spin_lock_bh(&ifp->lock);
1224 addrconf_del_timer(ifp); 1225 addrconf_del_timer(ifp);
@@ -1244,6 +1245,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1244 ipv6_del_addr(ifp); 1245 ipv6_del_addr(ifp);
1245} 1246}
1246 1247
1248void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1249{
1250 if (net_ratelimit())
1251 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
1252 addrconf_dad_stop(ifp);
1253}
1247 1254
1248/* Join to solicited addr multicast group. */ 1255/* Join to solicited addr multicast group. */
1249 1256
@@ -2136,6 +2143,37 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2136 2143
2137 switch(event) { 2144 switch(event) {
2138 case NETDEV_UP: 2145 case NETDEV_UP:
2146 case NETDEV_CHANGE:
2147 if (event == NETDEV_UP) {
2148 if (!netif_carrier_ok(dev)) {
2149 /* device is not ready yet. */
2150 printk(KERN_INFO
2151 "ADDRCONF(NETDEV_UP): %s: "
2152 "link is not ready\n",
2153 dev->name);
2154 break;
2155 }
2156 } else {
2157 if (!netif_carrier_ok(dev)) {
2158 /* device is still not ready. */
2159 break;
2160 }
2161
2162 if (idev) {
2163 if (idev->if_flags & IF_READY) {
2164 /* device is already configured. */
2165 break;
2166 }
2167 idev->if_flags |= IF_READY;
2168 }
2169
2170 printk(KERN_INFO
2171 "ADDRCONF(NETDEV_CHANGE): %s: "
2172 "link becomes ready\n",
2173 dev->name);
2174
2175 }
2176
2139 switch(dev->type) { 2177 switch(dev->type) {
2140 case ARPHRD_SIT: 2178 case ARPHRD_SIT:
2141 addrconf_sit_config(dev); 2179 addrconf_sit_config(dev);
@@ -2186,8 +2224,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2186 */ 2224 */
2187 addrconf_ifdown(dev, event != NETDEV_DOWN); 2225 addrconf_ifdown(dev, event != NETDEV_DOWN);
2188 break; 2226 break;
2189 case NETDEV_CHANGE: 2227
2190 break;
2191 case NETDEV_CHANGENAME: 2228 case NETDEV_CHANGENAME:
2192#ifdef CONFIG_SYSCTL 2229#ifdef CONFIG_SYSCTL
2193 if (idev) { 2230 if (idev) {
@@ -2268,7 +2305,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2268 2305
2269 /* Step 3: clear flags for stateless addrconf */ 2306 /* Step 3: clear flags for stateless addrconf */
2270 if (how != 1) 2307 if (how != 1)
2271 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD); 2308 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
2272 2309
2273 /* Step 4: clear address list */ 2310 /* Step 4: clear address list */
2274#ifdef CONFIG_IPV6_PRIVACY 2311#ifdef CONFIG_IPV6_PRIVACY
@@ -2377,11 +2414,20 @@ out:
2377/* 2414/*
2378 * Duplicate Address Detection 2415 * Duplicate Address Detection
2379 */ 2416 */
2417static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
2418{
2419 unsigned long rand_num;
2420 struct inet6_dev *idev = ifp->idev;
2421
2422 rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
2423 ifp->probes = idev->cnf.dad_transmits;
2424 addrconf_mod_timer(ifp, AC_DAD, rand_num);
2425}
2426
2380static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) 2427static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2381{ 2428{
2382 struct inet6_dev *idev = ifp->idev; 2429 struct inet6_dev *idev = ifp->idev;
2383 struct net_device *dev = idev->dev; 2430 struct net_device *dev = idev->dev;
2384 unsigned long rand_num;
2385 2431
2386 addrconf_join_solict(dev, &ifp->addr); 2432 addrconf_join_solict(dev, &ifp->addr);
2387 2433
@@ -2390,7 +2436,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2390 flags); 2436 flags);
2391 2437
2392 net_srandom(ifp->addr.s6_addr32[3]); 2438 net_srandom(ifp->addr.s6_addr32[3]);
2393 rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
2394 2439
2395 read_lock_bh(&idev->lock); 2440 read_lock_bh(&idev->lock);
2396 if (ifp->dead) 2441 if (ifp->dead)
@@ -2407,8 +2452,17 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2407 return; 2452 return;
2408 } 2453 }
2409 2454
2410 ifp->probes = idev->cnf.dad_transmits; 2455 if (idev->if_flags & IF_READY)
2411 addrconf_mod_timer(ifp, AC_DAD, rand_num); 2456 addrconf_dad_kick(ifp);
2457 else {
2458 /*
2459 * If the defice is not ready:
2460 * - keep it tentative if it is a permanent address.
2461 * - otherwise, kill it.
2462 */
2463 in6_ifa_hold(ifp);
2464 addrconf_dad_stop(ifp);
2465 }
2412 2466
2413 spin_unlock_bh(&ifp->lock); 2467 spin_unlock_bh(&ifp->lock);
2414out: 2468out: