addrconf.c (502a2ffd7376ae27cfde6172257db0ff9d8cfec2) addrconf.c (bcdd553fd3037d8700082ec4cbb6b25437ea06d6)
1/*
2 * IPv6 Address [auto]configuration
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8 *

--- 2442 unchanged lines hidden (view full) ---

2451 switch(event) {
2452 case NETDEV_REGISTER:
2453 if (!idev && dev->mtu >= IPV6_MIN_MTU) {
2454 idev = ipv6_add_dev(dev);
2455 if (!idev)
2456 return notifier_from_errno(-ENOMEM);
2457 }
2458 break;
1/*
2 * IPv6 Address [auto]configuration
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8 *

--- 2442 unchanged lines hidden (view full) ---

2451 switch(event) {
2452 case NETDEV_REGISTER:
2453 if (!idev && dev->mtu >= IPV6_MIN_MTU) {
2454 idev = ipv6_add_dev(dev);
2455 if (!idev)
2456 return notifier_from_errno(-ENOMEM);
2457 }
2458 break;
2459
2459 case NETDEV_UP:
2460 case NETDEV_CHANGE:
2461 if (dev->flags & IFF_SLAVE)
2462 break;
2463
2464 if (event == NETDEV_UP) {
2465 if (!addrconf_qdisc_ok(dev)) {
2466 /* device is not ready yet. */

--- 13 unchanged lines hidden (view full) ---

2480 }
2481 } else {
2482 if (!addrconf_qdisc_ok(dev)) {
2483 /* device is still not ready. */
2484 break;
2485 }
2486
2487 if (idev) {
2460 case NETDEV_UP:
2461 case NETDEV_CHANGE:
2462 if (dev->flags & IFF_SLAVE)
2463 break;
2464
2465 if (event == NETDEV_UP) {
2466 if (!addrconf_qdisc_ok(dev)) {
2467 /* device is not ready yet. */

--- 13 unchanged lines hidden (view full) ---

2481 }
2482 } else {
2483 if (!addrconf_qdisc_ok(dev)) {
2484 /* device is still not ready. */
2485 break;
2486 }
2487
2488 if (idev) {
2488 if (idev->if_flags & IF_READY) {
2489 if (idev->if_flags & IF_READY)
2489 /* device is already configured. */
2490 break;
2490 /* device is already configured. */
2491 break;
2491 }
2492 idev->if_flags |= IF_READY;
2493 }
2494
2495 printk(KERN_INFO
2496 "ADDRCONF(NETDEV_CHANGE): %s: "
2497 "link becomes ready\n",
2498 dev->name);
2499

--- 12 unchanged lines hidden (view full) ---

2512 case ARPHRD_LOOPBACK:
2513 init_loopback(dev);
2514 break;
2515
2516 default:
2517 addrconf_dev_config(dev);
2518 break;
2519 }
2492 idev->if_flags |= IF_READY;
2493 }
2494
2495 printk(KERN_INFO
2496 "ADDRCONF(NETDEV_CHANGE): %s: "
2497 "link becomes ready\n",
2498 dev->name);
2499

--- 12 unchanged lines hidden (view full) ---

2512 case ARPHRD_LOOPBACK:
2513 init_loopback(dev);
2514 break;
2515
2516 default:
2517 addrconf_dev_config(dev);
2518 break;
2519 }
2520
2520 if (idev) {
2521 if (run_pending)
2522 addrconf_dad_run(idev);
2523
2521 if (idev) {
2522 if (run_pending)
2523 addrconf_dad_run(idev);
2524
2524 /* If the MTU changed during the interface down, when the
2525 interface up, the changed MTU must be reflected in the
2526 idev as well as routers.
2525 /*
2526 * If the MTU changed during the interface down,
2527 * when the interface up, the changed MTU must be
2528 * reflected in the idev as well as routers.
2527 */
2529 */
2528 if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) {
2530 if (idev->cnf.mtu6 != dev->mtu &&
2531 dev->mtu >= IPV6_MIN_MTU) {
2529 rt6_mtu_change(dev, dev->mtu);
2530 idev->cnf.mtu6 = dev->mtu;
2531 }
2532 idev->tstamp = jiffies;
2533 inet6_ifinfo_notify(RTM_NEWLINK, idev);
2532 rt6_mtu_change(dev, dev->mtu);
2533 idev->cnf.mtu6 = dev->mtu;
2534 }
2535 idev->tstamp = jiffies;
2536 inet6_ifinfo_notify(RTM_NEWLINK, idev);
2534 /* If the changed mtu during down is lower than IPV6_MIN_MTU
2535 stop IPv6 on this interface.
2537
2538 /*
2539 * If the changed mtu during down is lower than
2540 * IPV6_MIN_MTU stop IPv6 on this interface.
2536 */
2537 if (dev->mtu < IPV6_MIN_MTU)
2541 */
2542 if (dev->mtu < IPV6_MIN_MTU)
2538 addrconf_ifdown(dev, event != NETDEV_DOWN);
2543 addrconf_ifdown(dev, 1);
2539 }
2540 break;
2541
2542 case NETDEV_CHANGEMTU:
2543 if (idev && dev->mtu >= IPV6_MIN_MTU) {
2544 rt6_mtu_change(dev, dev->mtu);
2545 idev->cnf.mtu6 = dev->mtu;
2546 break;
2547 }
2548
2549 if (!idev && dev->mtu >= IPV6_MIN_MTU) {
2550 idev = ipv6_add_dev(dev);
2551 if (idev)
2552 break;
2553 }
2554
2544 }
2545 break;
2546
2547 case NETDEV_CHANGEMTU:
2548 if (idev && dev->mtu >= IPV6_MIN_MTU) {
2549 rt6_mtu_change(dev, dev->mtu);
2550 idev->cnf.mtu6 = dev->mtu;
2551 break;
2552 }
2553
2554 if (!idev && dev->mtu >= IPV6_MIN_MTU) {
2555 idev = ipv6_add_dev(dev);
2556 if (idev)
2557 break;
2558 }
2559
2555 /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
2560 /*
2561 * MTU falled under IPV6_MIN_MTU.
2562 * Stop IPv6 on this interface.
2563 */
2556
2557 case NETDEV_DOWN:
2558 case NETDEV_UNREGISTER:
2559 /*
2560 * Remove all addresses from this interface.
2561 */
2562 addrconf_ifdown(dev, event != NETDEV_DOWN);
2563 break;
2564
2565 case NETDEV_CHANGENAME:
2566 if (idev) {
2567 snmp6_unregister_dev(idev);
2568 addrconf_sysctl_unregister(idev);
2569 addrconf_sysctl_register(idev);
2570 err = snmp6_register_dev(idev);
2571 if (err)
2572 return notifier_from_errno(err);
2573 }
2574 break;
2564
2565 case NETDEV_DOWN:
2566 case NETDEV_UNREGISTER:
2567 /*
2568 * Remove all addresses from this interface.
2569 */
2570 addrconf_ifdown(dev, event != NETDEV_DOWN);
2571 break;
2572
2573 case NETDEV_CHANGENAME:
2574 if (idev) {
2575 snmp6_unregister_dev(idev);
2576 addrconf_sysctl_unregister(idev);
2577 addrconf_sysctl_register(idev);
2578 err = snmp6_register_dev(idev);
2579 if (err)
2580 return notifier_from_errno(err);
2581 }
2582 break;
2583
2575 case NETDEV_PRE_TYPE_CHANGE:
2576 case NETDEV_POST_TYPE_CHANGE:
2577 addrconf_type_change(dev, event);
2578 break;
2579 }
2580
2581 return NOTIFY_OK;
2582}
2583
2584/*
2585 * addrconf module should be notified of a device going up
2586 */
2587static struct notifier_block ipv6_dev_notf = {
2588 .notifier_call = addrconf_notify,
2584 case NETDEV_PRE_TYPE_CHANGE:
2585 case NETDEV_POST_TYPE_CHANGE:
2586 addrconf_type_change(dev, event);
2587 break;
2588 }
2589
2590 return NOTIFY_OK;
2591}
2592
2593/*
2594 * addrconf module should be notified of a device going up
2595 */
2596static struct notifier_block ipv6_dev_notf = {
2597 .notifier_call = addrconf_notify,
2589 .priority = 0
2590};
2591
2592static void addrconf_type_change(struct net_device *dev, unsigned long event)
2593{
2594 struct inet6_dev *idev;
2595 ASSERT_RTNL();
2596
2597 idev = __in6_dev_get(dev);

--- 15 unchanged lines hidden (view full) ---

2613
2614 rt6_ifdown(net, dev);
2615 neigh_ifdown(&nd_tbl, dev);
2616
2617 idev = __in6_dev_get(dev);
2618 if (idev == NULL)
2619 return -ENODEV;
2620
2598};
2599
2600static void addrconf_type_change(struct net_device *dev, unsigned long event)
2601{
2602 struct inet6_dev *idev;
2603 ASSERT_RTNL();
2604
2605 idev = __in6_dev_get(dev);

--- 15 unchanged lines hidden (view full) ---

2621
2622 rt6_ifdown(net, dev);
2623 neigh_ifdown(&nd_tbl, dev);
2624
2625 idev = __in6_dev_get(dev);
2626 if (idev == NULL)
2627 return -ENODEV;
2628
2621 /* Step 1: remove reference to ipv6 device from parent device.
2622 Do not dev_put!
2629 /*
2630 * Step 1: remove reference to ipv6 device from parent device.
2631 * Do not dev_put!
2623 */
2624 if (how) {
2625 idev->dead = 1;
2626
2627 /* protected by rtnl_lock */
2628 rcu_assign_pointer(dev->ip6_ptr, NULL);
2629
2630 /* Step 1.5: remove snmp6 entry */
2631 snmp6_unregister_dev(idev);
2632
2633 }
2634
2635 write_lock_bh(&idev->lock);
2636
2632 */
2633 if (how) {
2634 idev->dead = 1;
2635
2636 /* protected by rtnl_lock */
2637 rcu_assign_pointer(dev->ip6_ptr, NULL);
2638
2639 /* Step 1.5: remove snmp6 entry */
2640 snmp6_unregister_dev(idev);
2641
2642 }
2643
2644 write_lock_bh(&idev->lock);
2645
2637 /* Step 3: clear flags for stateless addrconf */
2646 /* Step 2: clear flags for stateless addrconf */
2638 if (!how)
2639 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
2640
2647 if (!how)
2648 idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
2649
2641 /* Step 4: clear address list */
2642#ifdef CONFIG_IPV6_PRIVACY
2643 if (how && del_timer(&idev->regen_timer))
2644 in6_dev_put(idev);
2645
2650#ifdef CONFIG_IPV6_PRIVACY
2651 if (how && del_timer(&idev->regen_timer))
2652 in6_dev_put(idev);
2653
2646 /* clear tempaddr list */
2654 /* Step 3: clear tempaddr list */
2647 while (!list_empty(&idev->tempaddr_list)) {
2648 ifa = list_first_entry(&idev->tempaddr_list,
2649 struct inet6_ifaddr, tmp_list);
2650 list_del(&ifa->tmp_list);
2651 ifa->dead = 1;
2652 write_unlock_bh(&idev->lock);
2653 spin_lock_bh(&ifa->lock);
2654

--- 9 unchanged lines hidden (view full) ---

2664
2665 while (!list_empty(&idev->addr_list)) {
2666 ifa = list_first_entry(&idev->addr_list,
2667 struct inet6_ifaddr, if_list);
2668 addrconf_del_timer(ifa);
2669
2670 /* If just doing link down, and address is permanent
2671 and not link-local, then retain it. */
2655 while (!list_empty(&idev->tempaddr_list)) {
2656 ifa = list_first_entry(&idev->tempaddr_list,
2657 struct inet6_ifaddr, tmp_list);
2658 list_del(&ifa->tmp_list);
2659 ifa->dead = 1;
2660 write_unlock_bh(&idev->lock);
2661 spin_lock_bh(&ifa->lock);
2662

--- 9 unchanged lines hidden (view full) ---

2672
2673 while (!list_empty(&idev->addr_list)) {
2674 ifa = list_first_entry(&idev->addr_list,
2675 struct inet6_ifaddr, if_list);
2676 addrconf_del_timer(ifa);
2677
2678 /* If just doing link down, and address is permanent
2679 and not link-local, then retain it. */
2672 if (how == 0 &&
2680 if (!how &&
2673 (ifa->flags&IFA_F_PERMANENT) &&
2674 !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
2675 list_move_tail(&ifa->if_list, &keep_list);
2676
2677 /* If not doing DAD on this address, just keep it. */
2678 if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
2679 idev->cnf.accept_dad <= 0 ||
2680 (ifa->flags & IFA_F_NODAD))

--- 25 unchanged lines hidden (view full) ---

2706 write_lock_bh(&idev->lock);
2707 }
2708
2709 list_splice(&keep_list, &idev->addr_list);
2710
2711 write_unlock_bh(&idev->lock);
2712
2713 /* Step 5: Discard multicast list */
2681 (ifa->flags&IFA_F_PERMANENT) &&
2682 !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
2683 list_move_tail(&ifa->if_list, &keep_list);
2684
2685 /* If not doing DAD on this address, just keep it. */
2686 if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
2687 idev->cnf.accept_dad <= 0 ||
2688 (ifa->flags & IFA_F_NODAD))

--- 25 unchanged lines hidden (view full) ---

2714 write_lock_bh(&idev->lock);
2715 }
2716
2717 list_splice(&keep_list, &idev->addr_list);
2718
2719 write_unlock_bh(&idev->lock);
2720
2721 /* Step 5: Discard multicast list */
2714
2715 if (how)
2716 ipv6_mc_destroy_dev(idev);
2717 else
2718 ipv6_mc_down(idev);
2719
2720 idev->tstamp = jiffies;
2721
2722 if (how)
2723 ipv6_mc_destroy_dev(idev);
2724 else
2725 ipv6_mc_down(idev);
2726
2727 idev->tstamp = jiffies;
2728
2722 /* Shot the device (if unregistered) */
2723
2729 /* Last: Shot the device (if unregistered) */
2724 if (how) {
2725 addrconf_sysctl_unregister(idev);
2726 neigh_parms_release(&nd_tbl, idev->nd_parms);
2727 neigh_ifdown(&nd_tbl, dev);
2728 in6_dev_put(idev);
2729 }
2730 return 0;
2731}

--- 371 unchanged lines hidden (view full) ---

3103
3104 rcu_read_lock_bh();
3105 spin_lock(&addrconf_verify_lock);
3106 now = jiffies;
3107 next = now + ADDR_CHECK_FREQUENCY;
3108
3109 del_timer(&addr_chk_timer);
3110
2730 if (how) {
2731 addrconf_sysctl_unregister(idev);
2732 neigh_parms_release(&nd_tbl, idev->nd_parms);
2733 neigh_ifdown(&nd_tbl, dev);
2734 in6_dev_put(idev);
2735 }
2736 return 0;
2737}

--- 371 unchanged lines hidden (view full) ---

3109
3110 rcu_read_lock_bh();
3111 spin_lock(&addrconf_verify_lock);
3112 now = jiffies;
3113 next = now + ADDR_CHECK_FREQUENCY;
3114
3115 del_timer(&addr_chk_timer);
3116
3111 for (i=0; i < IN6_ADDR_HSIZE; i++) {
3112
3117 for (i = 0; i < IN6_ADDR_HSIZE; i++) {
3113restart:
3114 hlist_for_each_entry_rcu(ifp, node,
3115 &inet6_addr_lst[i], addr_lst) {
3116 unsigned long age;
3117#ifdef CONFIG_IPV6_PRIVACY
3118 unsigned long regen_advance;
3119#endif
3120

--- 1250 unchanged lines hidden (view full) ---

4371 { },
4372 };
4373
4374
4375 t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
4376 if (t == NULL)
4377 goto out;
4378
3118restart:
3119 hlist_for_each_entry_rcu(ifp, node,
3120 &inet6_addr_lst[i], addr_lst) {
3121 unsigned long age;
3122#ifdef CONFIG_IPV6_PRIVACY
3123 unsigned long regen_advance;
3124#endif
3125

--- 1250 unchanged lines hidden (view full) ---

4376 { },
4377 };
4378
4379
4380 t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
4381 if (t == NULL)
4382 goto out;
4383
4379 for (i=0; t->addrconf_vars[i].data; i++) {
4384 for (i = 0; t->addrconf_vars[i].data; i++) {
4380 t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
4381 t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
4382 t->addrconf_vars[i].extra2 = net;
4383 }
4384
4385 /*
4386 * Make a copy of dev_name, because '.procname' is regarded as const
4387 * by sysctl and we wouldn't want anyone to change it under our feet

--- 238 unchanged lines hidden ---
4385 t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
4386 t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
4387 t->addrconf_vars[i].extra2 = net;
4388 }
4389
4390 /*
4391 * Make a copy of dev_name, because '.procname' is regarded as const
4392 * by sysctl and we wouldn't want anyone to change it under our feet

--- 238 unchanged lines hidden ---