aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_addr.h1
-rw-r--r--include/net/addrconf.h6
-rw-r--r--net/ipv6/addrconf.c44
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);
61extern int ipv6_chk_addr(struct in6_addr *addr, 61extern 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
66static inline int ipv6_chk_home_addr(struct in6_addr *addr) 65extern int ipv6_chk_home_addr(struct in6_addr *addr);
67{
68 return 0;
69}
70#endif 66#endif
71extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, 67extern 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. */
2782int 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) {