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