aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-12-22 10:41:27 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2005-12-22 10:41:27 -0500
commite6469297d4eecfd9f46929fe1f56a01141cb0791 (patch)
tree9cdd368a9c5e02c177e54edcfd8bcc06155526a9 /net/ipv6/addrconf.c
parent9b78a82c1cf19aa813bdaa184fa840a3ba811750 (diff)
parent6b3ae80a63e47f6e97d68a1ddd520e3509e62821 (diff)
Merge git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+git+ipv6-fix-20051221a
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c106
1 files changed, 95 insertions, 11 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e717a034c953..510220f2ae8b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -137,6 +137,7 @@ static int addrconf_ifdown(struct net_device *dev, int how);
137static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); 137static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
138static void addrconf_dad_timer(unsigned long data); 138static void addrconf_dad_timer(unsigned long data);
139static void addrconf_dad_completed(struct inet6_ifaddr *ifp); 139static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
140static void addrconf_dad_run(struct inet6_dev *idev);
140static void addrconf_rs_timer(unsigned long data); 141static void addrconf_rs_timer(unsigned long data);
141static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); 142static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
142static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); 143static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
@@ -388,6 +389,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
388 } 389 }
389#endif 390#endif
390 391
392 if (netif_carrier_ok(dev))
393 ndev->if_flags |= IF_READY;
394
391 write_lock_bh(&addrconf_lock); 395 write_lock_bh(&addrconf_lock);
392 dev->ip6_ptr = ndev; 396 dev->ip6_ptr = ndev;
393 write_unlock_bh(&addrconf_lock); 397 write_unlock_bh(&addrconf_lock);
@@ -415,6 +419,7 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
415 if ((idev = ipv6_add_dev(dev)) == NULL) 419 if ((idev = ipv6_add_dev(dev)) == NULL)
416 return NULL; 420 return NULL;
417 } 421 }
422
418 if (dev->flags&IFF_UP) 423 if (dev->flags&IFF_UP)
419 ipv6_mc_up(idev); 424 ipv6_mc_up(idev);
420 return idev; 425 return idev;
@@ -904,11 +909,18 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
904 909
905 score.addr_type = __ipv6_addr_type(&ifa->addr); 910 score.addr_type = __ipv6_addr_type(&ifa->addr);
906 911
907 /* Rule 0: Candidate Source Address (section 4) 912 /* Rule 0:
913 * - Tentative Address (RFC2462 section 5.4)
914 * - A tentative address is not considered
915 * "assigned to an interface" in the traditional
916 * sense.
917 * - Candidate Source Address (section 4)
908 * - In any case, anycast addresses, multicast 918 * - In any case, anycast addresses, multicast
909 * addresses, and the unspecified address MUST 919 * addresses, and the unspecified address MUST
910 * NOT be included in a candidate set. 920 * NOT be included in a candidate set.
911 */ 921 */
922 if (ifa->flags & IFA_F_TENTATIVE)
923 continue;
912 if (unlikely(score.addr_type == IPV6_ADDR_ANY || 924 if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
913 score.addr_type & IPV6_ADDR_MULTICAST)) { 925 score.addr_type & IPV6_ADDR_MULTICAST)) {
914 LIMIT_NETDEBUG(KERN_DEBUG 926 LIMIT_NETDEBUG(KERN_DEBUG
@@ -1216,10 +1228,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
1216 1228
1217/* Gets referenced address, destroys ifaddr */ 1229/* Gets referenced address, destroys ifaddr */
1218 1230
1219void addrconf_dad_failure(struct inet6_ifaddr *ifp) 1231void addrconf_dad_stop(struct inet6_ifaddr *ifp)
1220{ 1232{
1221 if (net_ratelimit())
1222 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
1223 if (ifp->flags&IFA_F_PERMANENT) { 1233 if (ifp->flags&IFA_F_PERMANENT) {
1224 spin_lock_bh(&ifp->lock); 1234 spin_lock_bh(&ifp->lock);
1225 addrconf_del_timer(ifp); 1235 addrconf_del_timer(ifp);
@@ -1245,6 +1255,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1245 ipv6_del_addr(ifp); 1255 ipv6_del_addr(ifp);
1246} 1256}
1247 1257
1258void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1259{
1260 if (net_ratelimit())
1261 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
1262 addrconf_dad_stop(ifp);
1263}
1248 1264
1249/* Join to solicited addr multicast group. */ 1265/* Join to solicited addr multicast group. */
1250 1266
@@ -2134,9 +2150,42 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2134{ 2150{
2135 struct net_device *dev = (struct net_device *) data; 2151 struct net_device *dev = (struct net_device *) data;
2136 struct inet6_dev *idev = __in6_dev_get(dev); 2152 struct inet6_dev *idev = __in6_dev_get(dev);
2153 int run_pending = 0;
2137 2154
2138 switch(event) { 2155 switch(event) {
2139 case NETDEV_UP: 2156 case NETDEV_UP:
2157 case NETDEV_CHANGE:
2158 if (event == NETDEV_UP) {
2159 if (!netif_carrier_ok(dev)) {
2160 /* device is not ready yet. */
2161 printk(KERN_INFO
2162 "ADDRCONF(NETDEV_UP): %s: "
2163 "link is not ready\n",
2164 dev->name);
2165 break;
2166 }
2167 } else {
2168 if (!netif_carrier_ok(dev)) {
2169 /* device is still not ready. */
2170 break;
2171 }
2172
2173 if (idev) {
2174 if (idev->if_flags & IF_READY) {
2175 /* device is already configured. */
2176 break;
2177 }
2178 idev->if_flags |= IF_READY;
2179 }
2180
2181 printk(KERN_INFO
2182 "ADDRCONF(NETDEV_CHANGE): %s: "
2183 "link becomes ready\n",
2184 dev->name);
2185
2186 run_pending = 1;
2187 }
2188
2140 switch(dev->type) { 2189 switch(dev->type) {
2141 case ARPHRD_SIT: 2190 case ARPHRD_SIT:
2142 addrconf_sit_config(dev); 2191 addrconf_sit_config(dev);
@@ -2153,6 +2202,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2153 break; 2202 break;
2154 }; 2203 };
2155 if (idev) { 2204 if (idev) {
2205 if (run_pending)
2206 addrconf_dad_run(idev);
2207
2156 /* If the MTU changed during the interface down, when the 2208 /* If the MTU changed during the interface down, when the
2157 interface up, the changed MTU must be reflected in the 2209 interface up, the changed MTU must be reflected in the
2158 idev as well as routers. 2210 idev as well as routers.
@@ -2187,8 +2239,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2187 */ 2239 */
2188 addrconf_ifdown(dev, event != NETDEV_DOWN); 2240 addrconf_ifdown(dev, event != NETDEV_DOWN);
2189 break; 2241 break;
2190 case NETDEV_CHANGE: 2242
2191 break;
2192 case NETDEV_CHANGENAME: 2243 case NETDEV_CHANGENAME:
2193#ifdef CONFIG_SYSCTL 2244#ifdef CONFIG_SYSCTL
2194 if (idev) { 2245 if (idev) {
@@ -2269,7 +2320,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2269 2320
2270 /* Step 3: clear flags for stateless addrconf */ 2321 /* Step 3: clear flags for stateless addrconf */
2271 if (how != 1) 2322 if (how != 1)
2272 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD); 2323 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
2273 2324
2274 /* Step 4: clear address list */ 2325 /* Step 4: clear address list */
2275#ifdef CONFIG_IPV6_PRIVACY 2326#ifdef CONFIG_IPV6_PRIVACY
@@ -2378,11 +2429,20 @@ out:
2378/* 2429/*
2379 * Duplicate Address Detection 2430 * Duplicate Address Detection
2380 */ 2431 */
2432static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
2433{
2434 unsigned long rand_num;
2435 struct inet6_dev *idev = ifp->idev;
2436
2437 rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
2438 ifp->probes = idev->cnf.dad_transmits;
2439 addrconf_mod_timer(ifp, AC_DAD, rand_num);
2440}
2441
2381static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) 2442static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2382{ 2443{
2383 struct inet6_dev *idev = ifp->idev; 2444 struct inet6_dev *idev = ifp->idev;
2384 struct net_device *dev = idev->dev; 2445 struct net_device *dev = idev->dev;
2385 unsigned long rand_num;
2386 2446
2387 addrconf_join_solict(dev, &ifp->addr); 2447 addrconf_join_solict(dev, &ifp->addr);
2388 2448
@@ -2391,7 +2451,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2391 flags); 2451 flags);
2392 2452
2393 net_srandom(ifp->addr.s6_addr32[3]); 2453 net_srandom(ifp->addr.s6_addr32[3]);
2394 rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
2395 2454
2396 read_lock_bh(&idev->lock); 2455 read_lock_bh(&idev->lock);
2397 if (ifp->dead) 2456 if (ifp->dead)
@@ -2408,8 +2467,17 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2408 return; 2467 return;
2409 } 2468 }
2410 2469
2411 ifp->probes = idev->cnf.dad_transmits; 2470 if (idev->if_flags & IF_READY)
2412 addrconf_mod_timer(ifp, AC_DAD, rand_num); 2471 addrconf_dad_kick(ifp);
2472 else {
2473 /*
2474 * If the defice is not ready:
2475 * - keep it tentative if it is a permanent address.
2476 * - otherwise, kill it.
2477 */
2478 in6_ifa_hold(ifp);
2479 addrconf_dad_stop(ifp);
2480 }
2413 2481
2414 spin_unlock_bh(&ifp->lock); 2482 spin_unlock_bh(&ifp->lock);
2415out: 2483out:
@@ -2493,6 +2561,22 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
2493 } 2561 }
2494} 2562}
2495 2563
2564static void addrconf_dad_run(struct inet6_dev *idev) {
2565 struct inet6_ifaddr *ifp;
2566
2567 read_lock_bh(&idev->lock);
2568 for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) {
2569 spin_lock_bh(&ifp->lock);
2570 if (!(ifp->flags & IFA_F_TENTATIVE)) {
2571 spin_unlock_bh(&ifp->lock);
2572 continue;
2573 }
2574 spin_unlock_bh(&ifp->lock);
2575 addrconf_dad_kick(ifp);
2576 }
2577 read_unlock_bh(&idev->lock);
2578}
2579
2496#ifdef CONFIG_PROC_FS 2580#ifdef CONFIG_PROC_FS
2497struct if6_iter_state { 2581struct if6_iter_state {
2498 int bucket; 2582 int bucket;