diff options
author | Noriaki TAKAMIYA <takamiya@po.ntts.co.jp> | 2006-09-22 17:45:56 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:20:29 -0400 |
commit | 3b9f9a1c3903b64c38505f9fed3bb11e48dbc931 (patch) | |
tree | 0a508ef9ea7f9795d28333204c0a40c843b81e50 | |
parent | 55ebaef1d5db9c1c76ba01a87fd986db5dee550d (diff) |
[IPV6] ADDRCONF: Mobile IPv6 Home Address support.
IFA_F_HOMEADDRESS is introduced for Mobile IPv6 Home Addresses on
Mobile Node.
The IFA_F_HOMEADDRESS flag should be set for Mobile IPv6 Home
Addresses for 2 purposes. 1) We need to check this on receipt of
Type 2 Routing Header (RFC3775 Secion 6.4), 2) We prefer Home
Address(es) in source address selection (RFC3484 Section 5 Rule 4).
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/if_addr.h | 1 | ||||
-rw-r--r-- | include/net/addrconf.h | 6 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 44 |
3 files changed, 43 insertions, 8 deletions
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h index ca24b9de13fb..dbe8f6120a40 100644 --- a/include/linux/if_addr.h +++ b/include/linux/if_addr.h | |||
@@ -39,6 +39,7 @@ enum | |||
39 | #define IFA_F_TEMPORARY IFA_F_SECONDARY | 39 | #define IFA_F_TEMPORARY IFA_F_SECONDARY |
40 | 40 | ||
41 | #define IFA_F_NODAD 0x02 | 41 | #define IFA_F_NODAD 0x02 |
42 | #define IFA_F_HOMEADDRESS 0x10 | ||
42 | #define IFA_F_DEPRECATED 0x20 | 43 | #define IFA_F_DEPRECATED 0x20 |
43 | #define IFA_F_TENTATIVE 0x40 | 44 | #define IFA_F_TENTATIVE 0x40 |
44 | #define IFA_F_PERMANENT 0x80 | 45 | #define IFA_F_PERMANENT 0x80 |
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index aa2ed8f0a9dd..44f1b673f916 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -61,12 +61,8 @@ extern int addrconf_set_dstaddr(void __user *arg); | |||
61 | extern int ipv6_chk_addr(struct in6_addr *addr, | 61 | extern int ipv6_chk_addr(struct in6_addr *addr, |
62 | struct net_device *dev, | 62 | struct net_device *dev, |
63 | int strict); | 63 | int strict); |
64 | /* XXX: this is a placeholder till addrconf supports */ | ||
65 | #ifdef CONFIG_IPV6_MIP6 | 64 | #ifdef CONFIG_IPV6_MIP6 |
66 | static inline int ipv6_chk_home_addr(struct in6_addr *addr) | 65 | extern int ipv6_chk_home_addr(struct in6_addr *addr); |
67 | { | ||
68 | return 0; | ||
69 | } | ||
70 | #endif | 66 | #endif |
71 | extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, | 67 | extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, |
72 | struct net_device *dev, | 68 | struct net_device *dev, |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index adb583a26151..c18676352397 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1038,9 +1038,27 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
1038 | continue; | 1038 | continue; |
1039 | } | 1039 | } |
1040 | 1040 | ||
1041 | /* Rule 4: Prefer home address -- not implemented yet */ | 1041 | /* Rule 4: Prefer home address */ |
1042 | #ifdef CONFIG_IPV6_MIP6 | ||
1043 | if (hiscore.rule < 4) { | ||
1044 | if (ifa_result->flags & IFA_F_HOMEADDRESS) | ||
1045 | hiscore.attrs |= IPV6_SADDR_SCORE_HOA; | ||
1046 | hiscore.rule++; | ||
1047 | } | ||
1048 | if (ifa->flags & IFA_F_HOMEADDRESS) { | ||
1049 | score.attrs |= IPV6_SADDR_SCORE_HOA; | ||
1050 | if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) { | ||
1051 | score.rule = 4; | ||
1052 | goto record_it; | ||
1053 | } | ||
1054 | } else { | ||
1055 | if (hiscore.attrs & IPV6_SADDR_SCORE_HOA) | ||
1056 | continue; | ||
1057 | } | ||
1058 | #else | ||
1042 | if (hiscore.rule < 4) | 1059 | if (hiscore.rule < 4) |
1043 | hiscore.rule++; | 1060 | hiscore.rule++; |
1061 | #endif | ||
1044 | 1062 | ||
1045 | /* Rule 5: Prefer outgoing interface */ | 1063 | /* Rule 5: Prefer outgoing interface */ |
1046 | if (hiscore.rule < 5) { | 1064 | if (hiscore.rule < 5) { |
@@ -2759,6 +2777,26 @@ void if6_proc_exit(void) | |||
2759 | } | 2777 | } |
2760 | #endif /* CONFIG_PROC_FS */ | 2778 | #endif /* CONFIG_PROC_FS */ |
2761 | 2779 | ||
2780 | #ifdef CONFIG_IPV6_MIP6 | ||
2781 | /* Check if address is a home address configured on any interface. */ | ||
2782 | int ipv6_chk_home_addr(struct in6_addr *addr) | ||
2783 | { | ||
2784 | int ret = 0; | ||
2785 | struct inet6_ifaddr * ifp; | ||
2786 | u8 hash = ipv6_addr_hash(addr); | ||
2787 | read_lock_bh(&addrconf_hash_lock); | ||
2788 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | ||
2789 | if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && | ||
2790 | (ifp->flags & IFA_F_HOMEADDRESS)) { | ||
2791 | ret = 1; | ||
2792 | break; | ||
2793 | } | ||
2794 | } | ||
2795 | read_unlock_bh(&addrconf_hash_lock); | ||
2796 | return ret; | ||
2797 | } | ||
2798 | #endif | ||
2799 | |||
2762 | /* | 2800 | /* |
2763 | * Periodic address status verification | 2801 | * Periodic address status verification |
2764 | */ | 2802 | */ |
@@ -2930,7 +2968,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
2930 | prefered_lft = 0x7FFFFFFF/HZ; | 2968 | prefered_lft = 0x7FFFFFFF/HZ; |
2931 | 2969 | ||
2932 | spin_lock_bh(&ifp->lock); | 2970 | spin_lock_bh(&ifp->lock); |
2933 | ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD)) | ifa_flags; | 2971 | ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags; |
2934 | ifp->tstamp = jiffies; | 2972 | ifp->tstamp = jiffies; |
2935 | ifp->valid_lft = valid_lft; | 2973 | ifp->valid_lft = valid_lft; |
2936 | ifp->prefered_lft = prefered_lft; | 2974 | ifp->prefered_lft = prefered_lft; |
@@ -2981,7 +3019,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
2981 | return -ENODEV; | 3019 | return -ENODEV; |
2982 | 3020 | ||
2983 | /* We ignore other flags so far. */ | 3021 | /* We ignore other flags so far. */ |
2984 | ifa_flags = ifm->ifa_flags & IFA_F_NODAD; | 3022 | ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS); |
2985 | 3023 | ||
2986 | ifa = ipv6_get_ifaddr(pfx, dev, 1); | 3024 | ifa = ipv6_get_ifaddr(pfx, dev, 1); |
2987 | if (ifa == NULL) { | 3025 | if (ifa == NULL) { |