aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c17
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
914static inline int ipv6_saddr_preferred(int type) 915static 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
1032int ipv6_dev_get_saddr(struct net_device *dst_dev, 1041int 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;