diff options
| author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-03-01 20:48:21 -0500 |
|---|---|---|
| committer | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-03-24 21:23:58 -0400 |
| commit | a9b05723ffa2e427b0257b81ea74363fcd7c304f (patch) | |
| tree | 89f51b7d3fa28a83ab3f378f2fb6798e37bd21f0 | |
| parent | 9bb182a7007515239091b237fe7169b1328a61d3 (diff) | |
[IPV6] ADDRCONF: Clean-up ipv6_dev_get_saddr().
old:
| text data bss dec hex filename
| 28599 1416 96 30111 759f net/ipv6/addrconf.o
new:
| text data bss dec hex filename
| 28007 1416 96 29519 734f net/ipv6/addrconf.o
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
| -rw-r--r-- | net/ipv6/addrconf.c | 420 |
1 files changed, 206 insertions, 214 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4b86d388bf63..787e90af166c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -877,20 +877,39 @@ out: | |||
| 877 | /* | 877 | /* |
| 878 | * Choose an appropriate source address (RFC3484) | 878 | * Choose an appropriate source address (RFC3484) |
| 879 | */ | 879 | */ |
| 880 | enum { | ||
| 881 | IPV6_SADDR_RULE_INIT = 0, | ||
| 882 | IPV6_SADDR_RULE_LOCAL, | ||
| 883 | IPV6_SADDR_RULE_SCOPE, | ||
| 884 | IPV6_SADDR_RULE_PREFERRED, | ||
| 885 | #ifdef CONFIG_IPV6_MIP6 | ||
| 886 | IPV6_SADDR_RULE_HOA, | ||
| 887 | #endif | ||
| 888 | IPV6_SADDR_RULE_OIF, | ||
| 889 | IPV6_SADDR_RULE_LABEL, | ||
| 890 | #ifdef CONFIG_IPV6_PRIVACY | ||
| 891 | IPV6_SADDR_RULE_PRIVACY, | ||
| 892 | #endif | ||
| 893 | IPV6_SADDR_RULE_ORCHID, | ||
| 894 | IPV6_SADDR_RULE_PREFIX, | ||
| 895 | IPV6_SADDR_RULE_MAX | ||
| 896 | }; | ||
| 897 | |||
| 880 | struct ipv6_saddr_score { | 898 | struct ipv6_saddr_score { |
| 881 | int addr_type; | 899 | int rule; |
| 882 | unsigned int attrs; | 900 | int addr_type; |
| 883 | int matchlen; | 901 | struct inet6_ifaddr *ifa; |
| 884 | int scope; | 902 | DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX); |
| 885 | unsigned int rule; | 903 | int scopedist; |
| 904 | int matchlen; | ||
| 886 | }; | 905 | }; |
| 887 | 906 | ||
| 888 | #define IPV6_SADDR_SCORE_LOCAL 0x0001 | 907 | struct ipv6_saddr_dst { |
| 889 | #define IPV6_SADDR_SCORE_PREFERRED 0x0004 | 908 | struct in6_addr *addr; |
| 890 | #define IPV6_SADDR_SCORE_HOA 0x0008 | 909 | int ifindex; |
| 891 | #define IPV6_SADDR_SCORE_OIF 0x0010 | 910 | int scope; |
| 892 | #define IPV6_SADDR_SCORE_LABEL 0x0020 | 911 | int label; |
| 893 | #define IPV6_SADDR_SCORE_PRIVACY 0x0040 | 912 | }; |
| 894 | 913 | ||
| 895 | static inline int ipv6_saddr_preferred(int type) | 914 | static inline int ipv6_saddr_preferred(int type) |
| 896 | { | 915 | { |
| @@ -900,28 +919,142 @@ static inline int ipv6_saddr_preferred(int type) | |||
| 900 | return 0; | 919 | return 0; |
| 901 | } | 920 | } |
| 902 | 921 | ||
| 903 | int ipv6_dev_get_saddr(struct net_device *daddr_dev, | 922 | static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, |
| 923 | struct ipv6_saddr_dst *dst, | ||
| 924 | int i) | ||
| 925 | { | ||
| 926 | int ret; | ||
| 927 | |||
| 928 | if (i <= score->rule) { | ||
| 929 | switch (i) { | ||
| 930 | case IPV6_SADDR_RULE_SCOPE: | ||
| 931 | ret = score->scopedist; | ||
| 932 | break; | ||
| 933 | case IPV6_SADDR_RULE_PREFIX: | ||
| 934 | ret = score->matchlen; | ||
| 935 | break; | ||
| 936 | default: | ||
| 937 | ret = !!test_bit(i, score->scorebits); | ||
| 938 | } | ||
| 939 | goto out; | ||
| 940 | } | ||
| 941 | |||
| 942 | switch (i) { | ||
| 943 | case IPV6_SADDR_RULE_INIT: | ||
| 944 | /* Rule 0: remember if hiscore is not ready yet */ | ||
| 945 | ret = !!score->ifa; | ||
| 946 | break; | ||
| 947 | case IPV6_SADDR_RULE_LOCAL: | ||
| 948 | /* Rule 1: Prefer same address */ | ||
| 949 | ret = ipv6_addr_equal(&score->ifa->addr, dst->addr); | ||
| 950 | break; | ||
| 951 | case IPV6_SADDR_RULE_SCOPE: | ||
| 952 | /* Rule 2: Prefer appropriate scope | ||
| 953 | * | ||
| 954 | * ret | ||
| 955 | * ^ | ||
| 956 | * -1 | d 15 | ||
| 957 | * ---+--+-+---> scope | ||
| 958 | * | | ||
| 959 | * | d is scope of the destination. | ||
| 960 | * B-d | \ | ||
| 961 | * | \ <- smaller scope is better if | ||
| 962 | * B-15 | \ if scope is enough for destinaion. | ||
| 963 | * | ret = B - scope (-1 <= scope >= d <= 15). | ||
| 964 | * d-C-1 | / | ||
| 965 | * |/ <- greater is better | ||
| 966 | * -C / if scope is not enough for destination. | ||
| 967 | * /| ret = scope - C (-1 <= d < scope <= 15). | ||
| 968 | * | ||
| 969 | * d - C - 1 < B -15 (for all -1 <= d <= 15). | ||
| 970 | * C > d + 14 - B >= 15 + 14 - B = 29 - B. | ||
| 971 | * Assume B = 0 and we get C > 29. | ||
| 972 | */ | ||
| 973 | ret = __ipv6_addr_src_scope(score->addr_type); | ||
| 974 | if (ret >= dst->scope) | ||
| 975 | ret = -ret; | ||
| 976 | else | ||
| 977 | ret -= 128; /* 30 is enough */ | ||
| 978 | score->scopedist = ret; | ||
| 979 | break; | ||
| 980 | case IPV6_SADDR_RULE_PREFERRED: | ||
| 981 | /* Rule 3: Avoid deprecated and optimistic addresses */ | ||
| 982 | ret = ipv6_saddr_preferred(score->addr_type) || | ||
| 983 | !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)); | ||
| 984 | break; | ||
| 985 | #ifdef CONFIG_IPV6_MIP6 | ||
| 986 | case IPV6_SADDR_RULE_HOA: | ||
| 987 | /* Rule 4: Prefer home address */ | ||
| 988 | ret = !!(score->ifa->flags & IFA_F_HOMEADDRESS); | ||
| 989 | break; | ||
| 990 | #endif | ||
| 991 | case IPV6_SADDR_RULE_OIF: | ||
| 992 | /* Rule 5: Prefer outgoing interface */ | ||
| 993 | ret = (!dst->ifindex || | ||
| 994 | dst->ifindex == score->ifa->idev->dev->ifindex); | ||
| 995 | break; | ||
| 996 | case IPV6_SADDR_RULE_LABEL: | ||
| 997 | /* Rule 6: Prefer matching label */ | ||
| 998 | ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, | ||
| 999 | score->ifa->idev->dev->ifindex) == dst->label; | ||
| 1000 | break; | ||
| 1001 | #ifdef CONFIG_IPV6_PRIVACY | ||
| 1002 | case IPV6_SADDR_RULE_PRIVACY: | ||
| 1003 | /* Rule 7: Prefer public address | ||
| 1004 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
| 1005 | */ | ||
| 1006 | ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ (score->ifa->idev->cnf.use_tempaddr >= 2); | ||
| 1007 | break; | ||
| 1008 | #endif | ||
| 1009 | case IPV6_SADDR_RULE_ORCHID: | ||
| 1010 | /* Rule 8-: Prefer ORCHID vs ORCHID or | ||
| 1011 | * non-ORCHID vs non-ORCHID | ||
| 1012 | */ | ||
| 1013 | ret = !(ipv6_addr_orchid(&score->ifa->addr) ^ | ||
| 1014 | ipv6_addr_orchid(dst->addr)); | ||
| 1015 | break; | ||
| 1016 | case IPV6_SADDR_RULE_PREFIX: | ||
| 1017 | /* Rule 8: Use longest matching prefix */ | ||
| 1018 | score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr, | ||
| 1019 | dst->addr); | ||
| 1020 | break; | ||
| 1021 | default: | ||
| 1022 | ret = 0; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | if (ret) | ||
| 1026 | __set_bit(i, score->scorebits); | ||
| 1027 | score->rule = i; | ||
| 1028 | out: | ||
| 1029 | return ret; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | int ipv6_dev_get_saddr(struct net_device *dst_dev, | ||
| 904 | struct in6_addr *daddr, struct in6_addr *saddr) | 1033 | struct in6_addr *daddr, struct in6_addr *saddr) |
| 905 | { | 1034 | { |
| 906 | struct ipv6_saddr_score hiscore; | 1035 | struct ipv6_saddr_score scores[2], |
| 907 | struct inet6_ifaddr *ifa_result = NULL; | 1036 | *score = &scores[0], *hiscore = &scores[1]; |
| 908 | struct net *net = daddr_dev->nd_net; | 1037 | struct net *net = dst_dev->nd_net; |
| 909 | int daddr_type = __ipv6_addr_type(daddr); | 1038 | struct ipv6_saddr_dst dst; |
| 910 | int daddr_scope = __ipv6_addr_src_scope(daddr_type); | ||
| 911 | int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0; | ||
| 912 | u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex); | ||
| 913 | struct net_device *dev; | 1039 | struct net_device *dev; |
| 1040 | int dst_type; | ||
| 1041 | |||
| 1042 | dst_type = __ipv6_addr_type(daddr); | ||
| 1043 | dst.addr = daddr; | ||
| 1044 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; | ||
| 1045 | dst.scope = __ipv6_addr_src_scope(dst_type); | ||
| 1046 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); | ||
| 914 | 1047 | ||
| 915 | memset(&hiscore, 0, sizeof(hiscore)); | 1048 | hiscore->rule = -1; |
| 1049 | hiscore->ifa = NULL; | ||
| 916 | 1050 | ||
| 917 | read_lock(&dev_base_lock); | 1051 | read_lock(&dev_base_lock); |
| 918 | rcu_read_lock(); | 1052 | rcu_read_lock(); |
| 919 | 1053 | ||
| 920 | for_each_netdev(net, dev) { | 1054 | for_each_netdev(net, dev) { |
| 921 | struct inet6_dev *idev; | 1055 | struct inet6_dev *idev; |
| 922 | struct inet6_ifaddr *ifa; | ||
| 923 | 1056 | ||
| 924 | /* Rule 0: Candidate Source Address (section 4) | 1057 | /* Candidate Source Address (section 4) |
| 925 | * - multicast and link-local destination address, | 1058 | * - multicast and link-local destination address, |
| 926 | * the set of candidate source address MUST only | 1059 | * the set of candidate source address MUST only |
| 927 | * include addresses assigned to interfaces | 1060 | * include addresses assigned to interfaces |
| @@ -933,9 +1066,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 933 | * belonging to the same site as the outgoing | 1066 | * belonging to the same site as the outgoing |
| 934 | * interface.) | 1067 | * interface.) |
| 935 | */ | 1068 | */ |
| 936 | if ((daddr_type & IPV6_ADDR_MULTICAST || | 1069 | if (((dst_type & IPV6_ADDR_MULTICAST) || |
| 937 | daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && | 1070 | dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && |
| 938 | daddr_dev && dev != daddr_dev) | 1071 | dst.ifindex && dev->ifindex != dst.ifindex) |
| 939 | continue; | 1072 | continue; |
| 940 | 1073 | ||
| 941 | idev = __in6_dev_get(dev); | 1074 | idev = __in6_dev_get(dev); |
| @@ -943,12 +1076,10 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 943 | continue; | 1076 | continue; |
| 944 | 1077 | ||
| 945 | read_lock_bh(&idev->lock); | 1078 | read_lock_bh(&idev->lock); |
| 946 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1079 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { |
| 947 | struct ipv6_saddr_score score; | 1080 | int i; |
| 948 | 1081 | ||
| 949 | score.addr_type = __ipv6_addr_type(&ifa->addr); | 1082 | /* |
| 950 | |||
| 951 | /* Rule 0: | ||
| 952 | * - Tentative Address (RFC2462 section 5.4) | 1083 | * - Tentative Address (RFC2462 section 5.4) |
| 953 | * - A tentative address is not considered | 1084 | * - A tentative address is not considered |
| 954 | * "assigned to an interface" in the traditional | 1085 | * "assigned to an interface" in the traditional |
| @@ -958,11 +1089,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 958 | * addresses, and the unspecified address MUST | 1089 | * addresses, and the unspecified address MUST |
| 959 | * NOT be included in a candidate set. | 1090 | * NOT be included in a candidate set. |
| 960 | */ | 1091 | */ |
| 961 | if ((ifa->flags & IFA_F_TENTATIVE) && | 1092 | if ((score->ifa->flags & IFA_F_TENTATIVE) && |
| 962 | (!(ifa->flags & IFA_F_OPTIMISTIC))) | 1093 | (!(score->ifa->flags & IFA_F_OPTIMISTIC))) |
| 963 | continue; | 1094 | continue; |
| 964 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 1095 | |
| 965 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 1096 | score->addr_type = __ipv6_addr_type(&score->ifa->addr); |
| 1097 | |||
| 1098 | if (unlikely(score->addr_type == IPV6_ADDR_ANY || | ||
| 1099 | score->addr_type & IPV6_ADDR_MULTICAST)) { | ||
| 966 | LIMIT_NETDEBUG(KERN_DEBUG | 1100 | LIMIT_NETDEBUG(KERN_DEBUG |
| 967 | "ADDRCONF: unspecified / multicast address " | 1101 | "ADDRCONF: unspecified / multicast address " |
| 968 | "assigned as unicast address on %s", | 1102 | "assigned as unicast address on %s", |
| @@ -970,201 +1104,59 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 970 | continue; | 1104 | continue; |
| 971 | } | 1105 | } |
| 972 | 1106 | ||
| 973 | score.attrs = 0; | 1107 | score->rule = -1; |
| 974 | score.matchlen = 0; | 1108 | bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); |
| 975 | score.scope = 0; | 1109 | |
| 976 | score.rule = 0; | 1110 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { |
| 977 | 1111 | int minihiscore, miniscore; | |
| 978 | if (ifa_result == NULL) { | 1112 | |
| 979 | /* record it if the first available entry */ | 1113 | minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); |
| 980 | goto record_it; | 1114 | miniscore = ipv6_get_saddr_eval(score, &dst, i); |
| 981 | } | 1115 | |
| 982 | 1116 | if (minihiscore > miniscore) { | |
| 983 | /* Rule 1: Prefer same address */ | 1117 | if (i == IPV6_SADDR_RULE_SCOPE && |
| 984 | if (hiscore.rule < 1) { | 1118 | score->scopedist > 0) { |
| 985 | if (ipv6_addr_equal(&ifa_result->addr, daddr)) | 1119 | /* |
| 986 | hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL; | 1120 | * special case: |
| 987 | hiscore.rule++; | 1121 | * each remaining entry |
| 988 | } | 1122 | * has too small (not enough) |
| 989 | if (ipv6_addr_equal(&ifa->addr, daddr)) { | 1123 | * scope, because ifa entries |
| 990 | score.attrs |= IPV6_SADDR_SCORE_LOCAL; | 1124 | * are sorted by their scope |
| 991 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) { | 1125 | * values. |
| 992 | score.rule = 1; | 1126 | */ |
| 993 | goto record_it; | 1127 | goto try_nextdev; |
| 994 | } | 1128 | } |
| 995 | } else { | 1129 | break; |
| 996 | if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL) | 1130 | } else if (minihiscore < miniscore) { |
| 997 | continue; | 1131 | struct ipv6_saddr_score *tmp; |
| 998 | } | ||
| 999 | 1132 | ||
| 1000 | /* Rule 2: Prefer appropriate scope */ | 1133 | if (hiscore->ifa) |
| 1001 | if (hiscore.rule < 2) { | 1134 | in6_ifa_put(hiscore->ifa); |
| 1002 | hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type); | ||
| 1003 | hiscore.rule++; | ||
| 1004 | } | ||
| 1005 | score.scope = __ipv6_addr_src_scope(score.addr_type); | ||
| 1006 | if (hiscore.scope < score.scope) { | ||
| 1007 | if (hiscore.scope < daddr_scope) { | ||
| 1008 | score.rule = 2; | ||
| 1009 | goto record_it; | ||
| 1010 | } else | ||
| 1011 | continue; | ||
| 1012 | } else if (score.scope < hiscore.scope) { | ||
| 1013 | if (score.scope < daddr_scope) | ||
| 1014 | break; /* addresses sorted by scope */ | ||
| 1015 | else { | ||
| 1016 | score.rule = 2; | ||
| 1017 | goto record_it; | ||
| 1018 | } | ||
| 1019 | } | ||
| 1020 | 1135 | ||
| 1021 | /* Rule 3: Avoid deprecated and optimistic addresses */ | 1136 | in6_ifa_hold(score->ifa); |
| 1022 | if (hiscore.rule < 3) { | ||
| 1023 | if (ipv6_saddr_preferred(hiscore.addr_type) || | ||
| 1024 | (((ifa_result->flags & | ||
| 1025 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) | ||
| 1026 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
| 1027 | hiscore.rule++; | ||
| 1028 | } | ||
| 1029 | if (ipv6_saddr_preferred(score.addr_type) || | ||
| 1030 | (((ifa->flags & | ||
| 1031 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { | ||
| 1032 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
| 1033 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { | ||
| 1034 | score.rule = 3; | ||
| 1035 | goto record_it; | ||
| 1036 | } | ||
| 1037 | } else { | ||
| 1038 | if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED) | ||
| 1039 | continue; | ||
| 1040 | } | ||
| 1041 | 1137 | ||
| 1042 | /* Rule 4: Prefer home address */ | 1138 | tmp = hiscore; |
| 1043 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 1139 | hiscore = score; |
| 1044 | if (hiscore.rule < 4) { | 1140 | score = tmp; |
| 1045 | if (ifa_result->flags & IFA_F_HOMEADDRESS) | ||
| 1046 | hiscore.attrs |= IPV6_SADDR_SCORE_HOA; | ||
| 1047 | hiscore.rule++; | ||
| 1048 | } | ||
| 1049 | if (ifa->flags & IFA_F_HOMEADDRESS) { | ||
| 1050 | score.attrs |= IPV6_SADDR_SCORE_HOA; | ||
| 1051 | if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) { | ||
| 1052 | score.rule = 4; | ||
| 1053 | goto record_it; | ||
| 1054 | } | ||
| 1055 | } else { | ||
| 1056 | if (hiscore.attrs & IPV6_SADDR_SCORE_HOA) | ||
| 1057 | continue; | ||
| 1058 | } | ||
| 1059 | #else | ||
| 1060 | if (hiscore.rule < 4) | ||
| 1061 | hiscore.rule++; | ||
| 1062 | #endif | ||
| 1063 | 1141 | ||
| 1064 | /* Rule 5: Prefer outgoing interface */ | 1142 | /* restore our iterator */ |
| 1065 | if (hiscore.rule < 5) { | 1143 | score->ifa = hiscore->ifa; |
| 1066 | if (daddr_dev == NULL || | ||
| 1067 | daddr_dev == ifa_result->idev->dev) | ||
| 1068 | hiscore.attrs |= IPV6_SADDR_SCORE_OIF; | ||
| 1069 | hiscore.rule++; | ||
| 1070 | } | ||
| 1071 | if (daddr_dev == NULL || | ||
| 1072 | daddr_dev == ifa->idev->dev) { | ||
| 1073 | score.attrs |= IPV6_SADDR_SCORE_OIF; | ||
| 1074 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) { | ||
| 1075 | score.rule = 5; | ||
| 1076 | goto record_it; | ||
| 1077 | } | ||
| 1078 | } else { | ||
| 1079 | if (hiscore.attrs & IPV6_SADDR_SCORE_OIF) | ||
| 1080 | continue; | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | /* Rule 6: Prefer matching label */ | ||
| 1084 | if (hiscore.rule < 6) { | ||
| 1085 | if (ipv6_addr_label(&ifa_result->addr, | ||
| 1086 | hiscore.addr_type, | ||
| 1087 | ifa_result->idev->dev->ifindex) == daddr_label) | ||
| 1088 | hiscore.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
| 1089 | hiscore.rule++; | ||
| 1090 | } | ||
| 1091 | if (ipv6_addr_label(&ifa->addr, | ||
| 1092 | score.addr_type, | ||
| 1093 | ifa->idev->dev->ifindex) == daddr_label) { | ||
| 1094 | score.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
| 1095 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) { | ||
| 1096 | score.rule = 6; | ||
| 1097 | goto record_it; | ||
| 1098 | } | ||
| 1099 | } else { | ||
| 1100 | if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL) | ||
| 1101 | continue; | ||
| 1102 | } | ||
| 1103 | 1144 | ||
| 1104 | #ifdef CONFIG_IPV6_PRIVACY | 1145 | break; |
| 1105 | /* Rule 7: Prefer public address | ||
| 1106 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
| 1107 | */ | ||
| 1108 | if (hiscore.rule < 7) { | ||
| 1109 | if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^ | ||
| 1110 | (ifa_result->idev->cnf.use_tempaddr >= 2)) | ||
| 1111 | hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
| 1112 | hiscore.rule++; | ||
| 1113 | } | ||
| 1114 | if ((!(ifa->flags & IFA_F_TEMPORARY)) ^ | ||
| 1115 | (ifa->idev->cnf.use_tempaddr >= 2)) { | ||
| 1116 | score.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
| 1117 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) { | ||
| 1118 | score.rule = 7; | ||
| 1119 | goto record_it; | ||
| 1120 | } | 1146 | } |
| 1121 | } else { | ||
| 1122 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) | ||
| 1123 | continue; | ||
| 1124 | } | ||
| 1125 | #else | ||
| 1126 | if (hiscore.rule < 7) | ||
| 1127 | hiscore.rule++; | ||
| 1128 | #endif | ||
| 1129 | |||
| 1130 | /* Skip rule 8 for orchid -> non-orchid address pairs. */ | ||
| 1131 | if (ipv6_addr_orchid(&ifa->addr) && !ipv6_addr_orchid(daddr)) | ||
| 1132 | continue; | ||
| 1133 | |||
| 1134 | /* Rule 8: Use longest matching prefix */ | ||
| 1135 | if (hiscore.rule < 8) { | ||
| 1136 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | ||
| 1137 | hiscore.rule++; | ||
| 1138 | } | ||
| 1139 | score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); | ||
| 1140 | if (score.matchlen > hiscore.matchlen) { | ||
| 1141 | score.rule = 8; | ||
| 1142 | goto record_it; | ||
| 1143 | } | 1147 | } |
| 1144 | #if 0 | ||
| 1145 | else if (score.matchlen < hiscore.matchlen) | ||
| 1146 | continue; | ||
| 1147 | #endif | ||
| 1148 | |||
| 1149 | /* Final Rule: choose first available one */ | ||
| 1150 | continue; | ||
| 1151 | record_it: | ||
| 1152 | if (ifa_result) | ||
| 1153 | in6_ifa_put(ifa_result); | ||
| 1154 | in6_ifa_hold(ifa); | ||
| 1155 | ifa_result = ifa; | ||
| 1156 | hiscore = score; | ||
| 1157 | } | 1148 | } |
| 1149 | try_nextdev: | ||
| 1158 | read_unlock_bh(&idev->lock); | 1150 | read_unlock_bh(&idev->lock); |
| 1159 | } | 1151 | } |
| 1160 | rcu_read_unlock(); | 1152 | rcu_read_unlock(); |
| 1161 | read_unlock(&dev_base_lock); | 1153 | read_unlock(&dev_base_lock); |
| 1162 | 1154 | ||
| 1163 | if (!ifa_result) | 1155 | if (!hiscore->ifa) |
| 1164 | return -EADDRNOTAVAIL; | 1156 | return -EADDRNOTAVAIL; |
| 1165 | 1157 | ||
| 1166 | ipv6_addr_copy(saddr, &ifa_result->addr); | 1158 | ipv6_addr_copy(saddr, &hiscore->ifa->addr); |
| 1167 | in6_ifa_put(ifa_result); | 1159 | in6_ifa_put(hiscore->ifa); |
| 1168 | return 0; | 1160 | return 0; |
| 1169 | } | 1161 | } |
| 1170 | 1162 | ||
