diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 787e90af166c..89954885dee1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -909,6 +909,7 @@ struct ipv6_saddr_dst { | |||
909 | int ifindex; | 909 | int ifindex; |
910 | int scope; | 910 | int scope; |
911 | int label; | 911 | int label; |
912 | unsigned int prefs; | ||
912 | }; | 913 | }; |
913 | 914 | ||
914 | static inline int ipv6_saddr_preferred(int type) | 915 | static inline int ipv6_saddr_preferred(int type) |
@@ -984,9 +985,12 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, | |||
984 | break; | 985 | break; |
985 | #ifdef CONFIG_IPV6_MIP6 | 986 | #ifdef CONFIG_IPV6_MIP6 |
986 | case IPV6_SADDR_RULE_HOA: | 987 | case IPV6_SADDR_RULE_HOA: |
988 | { | ||
987 | /* Rule 4: Prefer home address */ | 989 | /* Rule 4: Prefer home address */ |
988 | ret = !!(score->ifa->flags & IFA_F_HOMEADDRESS); | 990 | int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA); |
991 | ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome; | ||
989 | break; | 992 | break; |
993 | } | ||
990 | #endif | 994 | #endif |
991 | case IPV6_SADDR_RULE_OIF: | 995 | case IPV6_SADDR_RULE_OIF: |
992 | /* Rule 5: Prefer outgoing interface */ | 996 | /* Rule 5: Prefer outgoing interface */ |
@@ -1000,11 +1004,16 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, | |||
1000 | break; | 1004 | break; |
1001 | #ifdef CONFIG_IPV6_PRIVACY | 1005 | #ifdef CONFIG_IPV6_PRIVACY |
1002 | case IPV6_SADDR_RULE_PRIVACY: | 1006 | case IPV6_SADDR_RULE_PRIVACY: |
1007 | { | ||
1003 | /* Rule 7: Prefer public address | 1008 | /* Rule 7: Prefer public address |
1004 | * Note: prefer temprary address if use_tempaddr >= 2 | 1009 | * Note: prefer temprary address if use_tempaddr >= 2 |
1005 | */ | 1010 | */ |
1006 | ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ (score->ifa->idev->cnf.use_tempaddr >= 2); | 1011 | int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? |
1012 | !!(dst->prefs & IPV6_PREFER_SRC_TMP) : | ||
1013 | score->ifa->idev->cnf.use_tempaddr >= 2; | ||
1014 | ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp; | ||
1007 | break; | 1015 | break; |
1016 | } | ||
1008 | #endif | 1017 | #endif |
1009 | case IPV6_SADDR_RULE_ORCHID: | 1018 | case IPV6_SADDR_RULE_ORCHID: |
1010 | /* Rule 8-: Prefer ORCHID vs ORCHID or | 1019 | /* Rule 8-: Prefer ORCHID vs ORCHID or |
@@ -1030,7 +1039,8 @@ out: | |||
1030 | } | 1039 | } |
1031 | 1040 | ||
1032 | int ipv6_dev_get_saddr(struct net_device *dst_dev, | 1041 | int ipv6_dev_get_saddr(struct net_device *dst_dev, |
1033 | struct in6_addr *daddr, struct in6_addr *saddr) | 1042 | struct in6_addr *daddr, unsigned int prefs, |
1043 | struct in6_addr *saddr) | ||
1034 | { | 1044 | { |
1035 | struct ipv6_saddr_score scores[2], | 1045 | struct ipv6_saddr_score scores[2], |
1036 | *score = &scores[0], *hiscore = &scores[1]; | 1046 | *score = &scores[0], *hiscore = &scores[1]; |
@@ -1044,6 +1054,7 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, | |||
1044 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; | 1054 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; |
1045 | dst.scope = __ipv6_addr_src_scope(dst_type); | 1055 | dst.scope = __ipv6_addr_src_scope(dst_type); |
1046 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); | 1056 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); |
1057 | dst.prefs = prefs; | ||
1047 | 1058 | ||
1048 | hiscore->rule = -1; | 1059 | hiscore->rule = -1; |
1049 | hiscore->ifa = NULL; | 1060 | hiscore->ifa = NULL; |