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 --- |