diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-09 01:07:12 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-09 01:07:12 -0500 |
commit | a892acacd3a8546ac161526522f13b5174f2c471 (patch) | |
tree | ee6d36f27f1388989ebfcabf90253fb7194112ac /net/ipv6 | |
parent | 193515d51ccb363165d6b09e9ba5c21089e34bad (diff) | |
parent | 330d57fb98a916fa8e1363846540dd420e99499a (diff) |
Merge branch 'master'
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 433 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 54 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 15 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 6 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 3 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 3 | ||||
-rw-r--r-- | net/ipv6/ipv6_syms.c | 2 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 15 |
8 files changed, 302 insertions, 229 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2c5f57299d63..b7a5f51238b3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -35,6 +35,9 @@ | |||
35 | * YOSHIFUJI Hideaki @USAGI : ARCnet support | 35 | * YOSHIFUJI Hideaki @USAGI : ARCnet support |
36 | * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to | 36 | * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to |
37 | * seq_file. | 37 | * seq_file. |
38 | * YOSHIFUJI Hideaki @USAGI : improved source address | ||
39 | * selection; consider scope, | ||
40 | * status etc. | ||
38 | */ | 41 | */ |
39 | 42 | ||
40 | #include <linux/config.h> | 43 | #include <linux/config.h> |
@@ -193,46 +196,51 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | |||
193 | #endif | 196 | #endif |
194 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | 197 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; |
195 | 198 | ||
196 | int ipv6_addr_type(const struct in6_addr *addr) | 199 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
200 | |||
201 | static inline unsigned ipv6_addr_scope2type(unsigned scope) | ||
202 | { | ||
203 | switch(scope) { | ||
204 | case IPV6_ADDR_SCOPE_NODELOCAL: | ||
205 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | | ||
206 | IPV6_ADDR_LOOPBACK); | ||
207 | case IPV6_ADDR_SCOPE_LINKLOCAL: | ||
208 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | | ||
209 | IPV6_ADDR_LINKLOCAL); | ||
210 | case IPV6_ADDR_SCOPE_SITELOCAL: | ||
211 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | | ||
212 | IPV6_ADDR_SITELOCAL); | ||
213 | } | ||
214 | return IPV6_ADDR_SCOPE_TYPE(scope); | ||
215 | } | ||
216 | |||
217 | int __ipv6_addr_type(const struct in6_addr *addr) | ||
197 | { | 218 | { |
198 | int type; | ||
199 | u32 st; | 219 | u32 st; |
200 | 220 | ||
201 | st = addr->s6_addr32[0]; | 221 | st = addr->s6_addr32[0]; |
202 | 222 | ||
203 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { | ||
204 | type = IPV6_ADDR_MULTICAST; | ||
205 | |||
206 | switch((st & htonl(0x00FF0000))) { | ||
207 | case __constant_htonl(0x00010000): | ||
208 | type |= IPV6_ADDR_LOOPBACK; | ||
209 | break; | ||
210 | |||
211 | case __constant_htonl(0x00020000): | ||
212 | type |= IPV6_ADDR_LINKLOCAL; | ||
213 | break; | ||
214 | |||
215 | case __constant_htonl(0x00050000): | ||
216 | type |= IPV6_ADDR_SITELOCAL; | ||
217 | break; | ||
218 | }; | ||
219 | return type; | ||
220 | } | ||
221 | |||
222 | type = IPV6_ADDR_UNICAST; | ||
223 | |||
224 | /* Consider all addresses with the first three bits different of | 223 | /* Consider all addresses with the first three bits different of |
225 | 000 and 111 as finished. | 224 | 000 and 111 as unicasts. |
226 | */ | 225 | */ |
227 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && | 226 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && |
228 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) | 227 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) |
229 | return type; | 228 | return (IPV6_ADDR_UNICAST | |
230 | 229 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); | |
231 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | 230 | |
232 | return (IPV6_ADDR_LINKLOCAL | type); | 231 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { |
232 | /* multicast */ | ||
233 | /* addr-select 3.1 */ | ||
234 | return (IPV6_ADDR_MULTICAST | | ||
235 | ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); | ||
236 | } | ||
233 | 237 | ||
238 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | ||
239 | return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | | ||
240 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ | ||
234 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) | 241 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) |
235 | return (IPV6_ADDR_SITELOCAL | type); | 242 | return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | |
243 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ | ||
236 | 244 | ||
237 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { | 245 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { |
238 | if (addr->s6_addr32[2] == 0) { | 246 | if (addr->s6_addr32[2] == 0) { |
@@ -240,24 +248,20 @@ int ipv6_addr_type(const struct in6_addr *addr) | |||
240 | return IPV6_ADDR_ANY; | 248 | return IPV6_ADDR_ANY; |
241 | 249 | ||
242 | if (addr->s6_addr32[3] == htonl(0x00000001)) | 250 | if (addr->s6_addr32[3] == htonl(0x00000001)) |
243 | return (IPV6_ADDR_LOOPBACK | type); | 251 | return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | |
252 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ | ||
244 | 253 | ||
245 | return (IPV6_ADDR_COMPATv4 | type); | 254 | return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | |
255 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | ||
246 | } | 256 | } |
247 | 257 | ||
248 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) | 258 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) |
249 | return IPV6_ADDR_MAPPED; | 259 | return (IPV6_ADDR_MAPPED | |
260 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | ||
250 | } | 261 | } |
251 | 262 | ||
252 | st &= htonl(0xFF000000); | 263 | return (IPV6_ADDR_RESERVED | |
253 | if (st == 0) | 264 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ |
254 | return IPV6_ADDR_RESERVED; | ||
255 | st &= htonl(0xFE000000); | ||
256 | if (st == htonl(0x02000000)) | ||
257 | return IPV6_ADDR_RESERVED; /* for NSAP */ | ||
258 | if (st == htonl(0x04000000)) | ||
259 | return IPV6_ADDR_RESERVED; /* for IPX */ | ||
260 | return type; | ||
261 | } | 265 | } |
262 | 266 | ||
263 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 267 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) |
@@ -805,138 +809,274 @@ out: | |||
805 | #endif | 809 | #endif |
806 | 810 | ||
807 | /* | 811 | /* |
808 | * Choose an appropriate source address | 812 | * Choose an appropriate source address (RFC3484) |
809 | * should do: | ||
810 | * i) get an address with an appropriate scope | ||
811 | * ii) see if there is a specific route for the destination and use | ||
812 | * an address of the attached interface | ||
813 | * iii) don't use deprecated addresses | ||
814 | */ | 813 | */ |
815 | static int inline ipv6_saddr_pref(const struct inet6_ifaddr *ifp, u8 invpref) | 814 | struct ipv6_saddr_score { |
815 | int addr_type; | ||
816 | unsigned int attrs; | ||
817 | int matchlen; | ||
818 | unsigned int scope; | ||
819 | unsigned int rule; | ||
820 | }; | ||
821 | |||
822 | #define IPV6_SADDR_SCORE_LOCAL 0x0001 | ||
823 | #define IPV6_SADDR_SCORE_PREFERRED 0x0004 | ||
824 | #define IPV6_SADDR_SCORE_HOA 0x0008 | ||
825 | #define IPV6_SADDR_SCORE_OIF 0x0010 | ||
826 | #define IPV6_SADDR_SCORE_LABEL 0x0020 | ||
827 | #define IPV6_SADDR_SCORE_PRIVACY 0x0040 | ||
828 | |||
829 | static int inline ipv6_saddr_preferred(int type) | ||
816 | { | 830 | { |
817 | int pref; | 831 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| |
818 | pref = ifp->flags&IFA_F_DEPRECATED ? 0 : 2; | 832 | IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) |
819 | #ifdef CONFIG_IPV6_PRIVACY | 833 | return 1; |
820 | pref |= (ifp->flags^invpref)&IFA_F_TEMPORARY ? 0 : 1; | 834 | return 0; |
821 | #endif | ||
822 | return pref; | ||
823 | } | 835 | } |
824 | 836 | ||
825 | #ifdef CONFIG_IPV6_PRIVACY | 837 | /* static matching label */ |
826 | #define IPV6_GET_SADDR_MAXSCORE(score) ((score) == 3) | 838 | static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) |
827 | #else | 839 | { |
828 | #define IPV6_GET_SADDR_MAXSCORE(score) (score) | 840 | /* |
829 | #endif | 841 | * prefix (longest match) label |
842 | * ----------------------------- | ||
843 | * ::1/128 0 | ||
844 | * ::/0 1 | ||
845 | * 2002::/16 2 | ||
846 | * ::/96 3 | ||
847 | * ::ffff:0:0/96 4 | ||
848 | */ | ||
849 | if (type & IPV6_ADDR_LOOPBACK) | ||
850 | return 0; | ||
851 | else if (type & IPV6_ADDR_COMPATv4) | ||
852 | return 3; | ||
853 | else if (type & IPV6_ADDR_MAPPED) | ||
854 | return 4; | ||
855 | else if (addr->s6_addr16[0] == htons(0x2002)) | ||
856 | return 2; | ||
857 | return 1; | ||
858 | } | ||
830 | 859 | ||
831 | int ipv6_dev_get_saddr(struct net_device *dev, | 860 | int ipv6_dev_get_saddr(struct net_device *daddr_dev, |
832 | struct in6_addr *daddr, struct in6_addr *saddr) | 861 | struct in6_addr *daddr, struct in6_addr *saddr) |
833 | { | 862 | { |
834 | struct inet6_ifaddr *ifp = NULL; | 863 | struct ipv6_saddr_score hiscore; |
835 | struct inet6_ifaddr *match = NULL; | 864 | struct inet6_ifaddr *ifa_result = NULL; |
836 | struct inet6_dev *idev; | 865 | int daddr_type = __ipv6_addr_type(daddr); |
837 | int scope; | 866 | int daddr_scope = __ipv6_addr_src_scope(daddr_type); |
838 | int err; | 867 | u32 daddr_label = ipv6_saddr_label(daddr, daddr_type); |
839 | int hiscore = -1, score; | 868 | struct net_device *dev; |
840 | 869 | ||
841 | scope = ipv6_addr_scope(daddr); | 870 | memset(&hiscore, 0, sizeof(hiscore)); |
842 | 871 | ||
843 | /* | 872 | read_lock(&dev_base_lock); |
844 | * known dev | 873 | read_lock(&addrconf_lock); |
845 | * search dev and walk through dev addresses | ||
846 | */ | ||
847 | 874 | ||
848 | if (dev) { | 875 | for (dev = dev_base; dev; dev=dev->next) { |
849 | if (dev->flags & IFF_LOOPBACK) | 876 | struct inet6_dev *idev; |
850 | scope = IFA_HOST; | 877 | struct inet6_ifaddr *ifa; |
878 | |||
879 | /* Rule 0: Candidate Source Address (section 4) | ||
880 | * - multicast and link-local destination address, | ||
881 | * the set of candidate source address MUST only | ||
882 | * include addresses assigned to interfaces | ||
883 | * belonging to the same link as the outgoing | ||
884 | * interface. | ||
885 | * (- For site-local destination addresses, the | ||
886 | * set of candidate source addresses MUST only | ||
887 | * include addresses assigned to interfaces | ||
888 | * belonging to the same site as the outgoing | ||
889 | * interface.) | ||
890 | */ | ||
891 | if ((daddr_type & IPV6_ADDR_MULTICAST || | ||
892 | daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && | ||
893 | daddr_dev && dev != daddr_dev) | ||
894 | continue; | ||
851 | 895 | ||
852 | read_lock(&addrconf_lock); | ||
853 | idev = __in6_dev_get(dev); | 896 | idev = __in6_dev_get(dev); |
854 | if (idev) { | 897 | if (!idev) |
855 | read_lock_bh(&idev->lock); | 898 | continue; |
856 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | ||
857 | if (ifp->scope == scope) { | ||
858 | if (ifp->flags&IFA_F_TENTATIVE) | ||
859 | continue; | ||
860 | #ifdef CONFIG_IPV6_PRIVACY | ||
861 | score = ipv6_saddr_pref(ifp, idev->cnf.use_tempaddr > 1 ? IFA_F_TEMPORARY : 0); | ||
862 | #else | ||
863 | score = ipv6_saddr_pref(ifp, 0); | ||
864 | #endif | ||
865 | if (score <= hiscore) | ||
866 | continue; | ||
867 | 899 | ||
868 | if (match) | 900 | read_lock_bh(&idev->lock); |
869 | in6_ifa_put(match); | 901 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { |
870 | match = ifp; | 902 | struct ipv6_saddr_score score; |
871 | hiscore = score; | ||
872 | in6_ifa_hold(ifp); | ||
873 | 903 | ||
874 | if (IPV6_GET_SADDR_MAXSCORE(score)) { | 904 | score.addr_type = __ipv6_addr_type(&ifa->addr); |
875 | read_unlock_bh(&idev->lock); | 905 | |
876 | read_unlock(&addrconf_lock); | 906 | /* Rule 0: Candidate Source Address (section 4) |
877 | goto out; | 907 | * - In any case, anycast addresses, multicast |
878 | } | 908 | * addresses, and the unspecified address MUST |
909 | * NOT be included in a candidate set. | ||
910 | */ | ||
911 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | ||
912 | score.addr_type & IPV6_ADDR_MULTICAST)) { | ||
913 | LIMIT_NETDEBUG(KERN_DEBUG | ||
914 | "ADDRCONF: unspecified / multicast address" | ||
915 | "assigned as unicast address on %s", | ||
916 | dev->name); | ||
917 | continue; | ||
918 | } | ||
919 | |||
920 | score.attrs = 0; | ||
921 | score.matchlen = 0; | ||
922 | score.scope = 0; | ||
923 | score.rule = 0; | ||
924 | |||
925 | if (ifa_result == NULL) { | ||
926 | /* record it if the first available entry */ | ||
927 | goto record_it; | ||
928 | } | ||
929 | |||
930 | /* Rule 1: Prefer same address */ | ||
931 | if (hiscore.rule < 1) { | ||
932 | if (ipv6_addr_equal(&ifa_result->addr, daddr)) | ||
933 | hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL; | ||
934 | hiscore.rule++; | ||
935 | } | ||
936 | if (ipv6_addr_equal(&ifa->addr, daddr)) { | ||
937 | score.attrs |= IPV6_SADDR_SCORE_LOCAL; | ||
938 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) { | ||
939 | score.rule = 1; | ||
940 | goto record_it; | ||
879 | } | 941 | } |
942 | } else { | ||
943 | if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL) | ||
944 | continue; | ||
880 | } | 945 | } |
881 | read_unlock_bh(&idev->lock); | ||
882 | } | ||
883 | read_unlock(&addrconf_lock); | ||
884 | } | ||
885 | 946 | ||
886 | if (scope == IFA_LINK) | 947 | /* Rule 2: Prefer appropriate scope */ |
887 | goto out; | 948 | if (hiscore.rule < 2) { |
949 | hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type); | ||
950 | hiscore.rule++; | ||
951 | } | ||
952 | score.scope = __ipv6_addr_src_scope(score.addr_type); | ||
953 | if (hiscore.scope < score.scope) { | ||
954 | if (hiscore.scope < daddr_scope) { | ||
955 | score.rule = 2; | ||
956 | goto record_it; | ||
957 | } else | ||
958 | continue; | ||
959 | } else if (score.scope < hiscore.scope) { | ||
960 | if (score.scope < daddr_scope) | ||
961 | continue; | ||
962 | else { | ||
963 | score.rule = 2; | ||
964 | goto record_it; | ||
965 | } | ||
966 | } | ||
888 | 967 | ||
889 | /* | 968 | /* Rule 3: Avoid deprecated address */ |
890 | * dev == NULL or search failed for specified dev | 969 | if (hiscore.rule < 3) { |
891 | */ | 970 | if (ipv6_saddr_preferred(hiscore.addr_type) || |
971 | !(ifa_result->flags & IFA_F_DEPRECATED)) | ||
972 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
973 | hiscore.rule++; | ||
974 | } | ||
975 | if (ipv6_saddr_preferred(score.addr_type) || | ||
976 | !(ifa->flags & IFA_F_DEPRECATED)) { | ||
977 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
978 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { | ||
979 | score.rule = 3; | ||
980 | goto record_it; | ||
981 | } | ||
982 | } else { | ||
983 | if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED) | ||
984 | continue; | ||
985 | } | ||
892 | 986 | ||
893 | read_lock(&dev_base_lock); | 987 | /* Rule 4: Prefer home address -- not implemented yet */ |
894 | read_lock(&addrconf_lock); | ||
895 | for (dev = dev_base; dev; dev=dev->next) { | ||
896 | idev = __in6_dev_get(dev); | ||
897 | if (idev) { | ||
898 | read_lock_bh(&idev->lock); | ||
899 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | ||
900 | if (ifp->scope == scope) { | ||
901 | if (ifp->flags&IFA_F_TENTATIVE) | ||
902 | continue; | ||
903 | #ifdef CONFIG_IPV6_PRIVACY | ||
904 | score = ipv6_saddr_pref(ifp, idev->cnf.use_tempaddr > 1 ? IFA_F_TEMPORARY : 0); | ||
905 | #else | ||
906 | score = ipv6_saddr_pref(ifp, 0); | ||
907 | #endif | ||
908 | if (score <= hiscore) | ||
909 | continue; | ||
910 | 988 | ||
911 | if (match) | 989 | /* Rule 5: Prefer outgoing interface */ |
912 | in6_ifa_put(match); | 990 | if (hiscore.rule < 5) { |
913 | match = ifp; | 991 | if (daddr_dev == NULL || |
914 | hiscore = score; | 992 | daddr_dev == ifa_result->idev->dev) |
915 | in6_ifa_hold(ifp); | 993 | hiscore.attrs |= IPV6_SADDR_SCORE_OIF; |
994 | hiscore.rule++; | ||
995 | } | ||
996 | if (daddr_dev == NULL || | ||
997 | daddr_dev == ifa->idev->dev) { | ||
998 | score.attrs |= IPV6_SADDR_SCORE_OIF; | ||
999 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) { | ||
1000 | score.rule = 5; | ||
1001 | goto record_it; | ||
1002 | } | ||
1003 | } else { | ||
1004 | if (hiscore.attrs & IPV6_SADDR_SCORE_OIF) | ||
1005 | continue; | ||
1006 | } | ||
916 | 1007 | ||
917 | if (IPV6_GET_SADDR_MAXSCORE(score)) { | 1008 | /* Rule 6: Prefer matching label */ |
918 | read_unlock_bh(&idev->lock); | 1009 | if (hiscore.rule < 6) { |
919 | goto out_unlock_base; | 1010 | if (ipv6_saddr_label(&ifa_result->addr, hiscore.addr_type) == daddr_label) |
920 | } | 1011 | hiscore.attrs |= IPV6_SADDR_SCORE_LABEL; |
1012 | hiscore.rule++; | ||
1013 | } | ||
1014 | if (ipv6_saddr_label(&ifa->addr, score.addr_type) == daddr_label) { | ||
1015 | score.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
1016 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) { | ||
1017 | score.rule = 6; | ||
1018 | goto record_it; | ||
1019 | } | ||
1020 | } else { | ||
1021 | if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL) | ||
1022 | continue; | ||
1023 | } | ||
1024 | |||
1025 | /* Rule 7: Prefer public address | ||
1026 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
1027 | */ | ||
1028 | if (hiscore.rule < 7) { | ||
1029 | if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^ | ||
1030 | (ifa_result->idev->cnf.use_tempaddr >= 2)) | ||
1031 | hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
1032 | hiscore.rule++; | ||
1033 | } | ||
1034 | if ((!(ifa->flags & IFA_F_TEMPORARY)) ^ | ||
1035 | (ifa->idev->cnf.use_tempaddr >= 2)) { | ||
1036 | score.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
1037 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) { | ||
1038 | score.rule = 7; | ||
1039 | goto record_it; | ||
921 | } | 1040 | } |
1041 | } else { | ||
1042 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) | ||
1043 | continue; | ||
922 | } | 1044 | } |
923 | read_unlock_bh(&idev->lock); | 1045 | |
1046 | /* Rule 8: Use longest matching prefix */ | ||
1047 | if (hiscore.rule < 8) | ||
1048 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | ||
1049 | score.rule++; | ||
1050 | score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); | ||
1051 | if (score.matchlen > hiscore.matchlen) { | ||
1052 | score.rule = 8; | ||
1053 | goto record_it; | ||
1054 | } | ||
1055 | #if 0 | ||
1056 | else if (score.matchlen < hiscore.matchlen) | ||
1057 | continue; | ||
1058 | #endif | ||
1059 | |||
1060 | /* Final Rule: choose first available one */ | ||
1061 | continue; | ||
1062 | record_it: | ||
1063 | if (ifa_result) | ||
1064 | in6_ifa_put(ifa_result); | ||
1065 | in6_ifa_hold(ifa); | ||
1066 | ifa_result = ifa; | ||
1067 | hiscore = score; | ||
924 | } | 1068 | } |
1069 | read_unlock_bh(&idev->lock); | ||
925 | } | 1070 | } |
926 | |||
927 | out_unlock_base: | ||
928 | read_unlock(&addrconf_lock); | 1071 | read_unlock(&addrconf_lock); |
929 | read_unlock(&dev_base_lock); | 1072 | read_unlock(&dev_base_lock); |
930 | 1073 | ||
931 | out: | 1074 | if (!ifa_result) |
932 | err = -EADDRNOTAVAIL; | 1075 | return -EADDRNOTAVAIL; |
933 | if (match) { | 1076 | |
934 | ipv6_addr_copy(saddr, &match->addr); | 1077 | ipv6_addr_copy(saddr, &ifa_result->addr); |
935 | err = 0; | 1078 | in6_ifa_put(ifa_result); |
936 | in6_ifa_put(match); | 1079 | return 0; |
937 | } | ||
938 | |||
939 | return err; | ||
940 | } | 1080 | } |
941 | 1081 | ||
942 | 1082 | ||
@@ -2950,8 +3090,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | |||
2950 | 3090 | ||
2951 | nlmsg_failure: | 3091 | nlmsg_failure: |
2952 | rtattr_failure: | 3092 | rtattr_failure: |
2953 | if (array) | 3093 | kfree(array); |
2954 | kfree(array); | ||
2955 | skb_trim(skb, b - skb->data); | 3094 | skb_trim(skb, b - skb->data); |
2956 | return -1; | 3095 | return -1; |
2957 | } | 3096 | } |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 4fcc5a7acf6e..1bf6d9a769e6 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -127,56 +127,6 @@ static __inline__ int addr_bit_set(void *token, int fn_bit) | |||
127 | return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; | 127 | return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; |
128 | } | 128 | } |
129 | 129 | ||
130 | /* | ||
131 | * find the first different bit between two addresses | ||
132 | * length of address must be a multiple of 32bits | ||
133 | */ | ||
134 | |||
135 | static __inline__ int addr_diff(void *token1, void *token2, int addrlen) | ||
136 | { | ||
137 | __u32 *a1 = token1; | ||
138 | __u32 *a2 = token2; | ||
139 | int i; | ||
140 | |||
141 | addrlen >>= 2; | ||
142 | |||
143 | for (i = 0; i < addrlen; i++) { | ||
144 | __u32 xb; | ||
145 | |||
146 | xb = a1[i] ^ a2[i]; | ||
147 | |||
148 | if (xb) { | ||
149 | int j = 31; | ||
150 | |||
151 | xb = ntohl(xb); | ||
152 | |||
153 | while ((xb & (1 << j)) == 0) | ||
154 | j--; | ||
155 | |||
156 | return (i * 32 + 31 - j); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * we should *never* get to this point since that | ||
162 | * would mean the addrs are equal | ||
163 | * | ||
164 | * However, we do get to it 8) And exacly, when | ||
165 | * addresses are equal 8) | ||
166 | * | ||
167 | * ip route add 1111::/128 via ... | ||
168 | * ip route add 1111::/64 via ... | ||
169 | * and we are here. | ||
170 | * | ||
171 | * Ideally, this function should stop comparison | ||
172 | * at prefix length. It does not, but it is still OK, | ||
173 | * if returned value is greater than prefix length. | ||
174 | * --ANK (980803) | ||
175 | */ | ||
176 | |||
177 | return addrlen<<5; | ||
178 | } | ||
179 | |||
180 | static __inline__ struct fib6_node * node_alloc(void) | 130 | static __inline__ struct fib6_node * node_alloc(void) |
181 | { | 131 | { |
182 | struct fib6_node *fn; | 132 | struct fib6_node *fn; |
@@ -296,11 +246,11 @@ insert_above: | |||
296 | 246 | ||
297 | /* find 1st bit in difference between the 2 addrs. | 247 | /* find 1st bit in difference between the 2 addrs. |
298 | 248 | ||
299 | See comment in addr_diff: bit may be an invalid value, | 249 | See comment in __ipv6_addr_diff: bit may be an invalid value, |
300 | but if it is >= plen, the value is ignored in any case. | 250 | but if it is >= plen, the value is ignored in any case. |
301 | */ | 251 | */ |
302 | 252 | ||
303 | bit = addr_diff(addr, &key->addr, addrlen); | 253 | bit = __ipv6_addr_diff(addr, &key->addr, addrlen); |
304 | 254 | ||
305 | /* | 255 | /* |
306 | * (intermediate)[in] | 256 | * (intermediate)[in] |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 614296a920c6..dbd9767b32e4 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -587,8 +587,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
587 | skb->next = NULL; | 587 | skb->next = NULL; |
588 | } | 588 | } |
589 | 589 | ||
590 | if (tmp_hdr) | 590 | kfree(tmp_hdr); |
591 | kfree(tmp_hdr); | ||
592 | 591 | ||
593 | if (err == 0) { | 592 | if (err == 0) { |
594 | IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); | 593 | IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); |
@@ -1186,10 +1185,8 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1186 | 1185 | ||
1187 | out: | 1186 | out: |
1188 | inet->cork.flags &= ~IPCORK_OPT; | 1187 | inet->cork.flags &= ~IPCORK_OPT; |
1189 | if (np->cork.opt) { | 1188 | kfree(np->cork.opt); |
1190 | kfree(np->cork.opt); | 1189 | np->cork.opt = NULL; |
1191 | np->cork.opt = NULL; | ||
1192 | } | ||
1193 | if (np->cork.rt) { | 1190 | if (np->cork.rt) { |
1194 | dst_release(&np->cork.rt->u.dst); | 1191 | dst_release(&np->cork.rt->u.dst); |
1195 | np->cork.rt = NULL; | 1192 | np->cork.rt = NULL; |
@@ -1214,10 +1211,8 @@ void ip6_flush_pending_frames(struct sock *sk) | |||
1214 | 1211 | ||
1215 | inet->cork.flags &= ~IPCORK_OPT; | 1212 | inet->cork.flags &= ~IPCORK_OPT; |
1216 | 1213 | ||
1217 | if (np->cork.opt) { | 1214 | kfree(np->cork.opt); |
1218 | kfree(np->cork.opt); | 1215 | np->cork.opt = NULL; |
1219 | np->cork.opt = NULL; | ||
1220 | } | ||
1221 | if (np->cork.rt) { | 1216 | if (np->cork.rt) { |
1222 | dst_release(&np->cork.rt->u.dst); | 1217 | dst_release(&np->cork.rt->u.dst); |
1223 | np->cork.rt = NULL; | 1218 | np->cork.rt = NULL; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index cf94372d1af3..e6b0e3954c02 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -756,8 +756,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
756 | } | 756 | } |
757 | ip6_tnl_dst_store(t, dst); | 757 | ip6_tnl_dst_store(t, dst); |
758 | 758 | ||
759 | if (opt) | 759 | kfree(opt); |
760 | kfree(opt); | ||
761 | 760 | ||
762 | t->recursion--; | 761 | t->recursion--; |
763 | return 0; | 762 | return 0; |
@@ -766,8 +765,7 @@ tx_err_link_failure: | |||
766 | dst_link_failure(skb); | 765 | dst_link_failure(skb); |
767 | tx_err_dst_release: | 766 | tx_err_dst_release: |
768 | dst_release(dst); | 767 | dst_release(dst); |
769 | if (opt) | 768 | kfree(opt); |
770 | kfree(opt); | ||
771 | tx_err: | 769 | tx_err: |
772 | stats->tx_errors++; | 770 | stats->tx_errors++; |
773 | stats->tx_dropped++; | 771 | stats->tx_dropped++; |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 85bfbc69b2c3..55917fb17094 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -130,8 +130,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s | |||
130 | out_put_cpu: | 130 | out_put_cpu: |
131 | put_cpu(); | 131 | put_cpu(); |
132 | out: | 132 | out: |
133 | if (tmp_hdr) | 133 | kfree(tmp_hdr); |
134 | kfree(tmp_hdr); | ||
135 | if (err) | 134 | if (err) |
136 | goto error_out; | 135 | goto error_out; |
137 | return nexthdr; | 136 | return nexthdr; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 8567873d0dd8..003fd99ff597 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -80,8 +80,7 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) | |||
80 | if (ra->sk == sk) { | 80 | if (ra->sk == sk) { |
81 | if (sel>=0) { | 81 | if (sel>=0) { |
82 | write_unlock_bh(&ip6_ra_lock); | 82 | write_unlock_bh(&ip6_ra_lock); |
83 | if (new_ra) | 83 | kfree(new_ra); |
84 | kfree(new_ra); | ||
85 | return -EADDRINUSE; | 84 | return -EADDRINUSE; |
86 | } | 85 | } |
87 | 86 | ||
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 37a4a99c9fe9..16482785bdfd 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <net/ip6_route.h> | 7 | #include <net/ip6_route.h> |
8 | #include <net/xfrm.h> | 8 | #include <net/xfrm.h> |
9 | 9 | ||
10 | EXPORT_SYMBOL(ipv6_addr_type); | 10 | EXPORT_SYMBOL(__ipv6_addr_type); |
11 | EXPORT_SYMBOL(icmpv6_send); | 11 | EXPORT_SYMBOL(icmpv6_send); |
12 | EXPORT_SYMBOL(icmpv6_statistics); | 12 | EXPORT_SYMBOL(icmpv6_statistics); |
13 | EXPORT_SYMBOL(icmpv6_err_convert); | 13 | EXPORT_SYMBOL(icmpv6_err_convert); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d693cb988b78..d746d3b27efb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -114,16 +114,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) | |||
114 | int low = sysctl_local_port_range[0]; | 114 | int low = sysctl_local_port_range[0]; |
115 | int high = sysctl_local_port_range[1]; | 115 | int high = sysctl_local_port_range[1]; |
116 | int remaining = (high - low) + 1; | 116 | int remaining = (high - low) + 1; |
117 | int rover; | 117 | int rover = net_random() % (high - low) + low; |
118 | 118 | ||
119 | spin_lock(&tcp_hashinfo.portalloc_lock); | 119 | do { |
120 | if (tcp_hashinfo.port_rover < low) | ||
121 | rover = low; | ||
122 | else | ||
123 | rover = tcp_hashinfo.port_rover; | ||
124 | do { rover++; | ||
125 | if (rover > high) | ||
126 | rover = low; | ||
127 | head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)]; | 120 | head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)]; |
128 | spin_lock(&head->lock); | 121 | spin_lock(&head->lock); |
129 | inet_bind_bucket_for_each(tb, node, &head->chain) | 122 | inet_bind_bucket_for_each(tb, node, &head->chain) |
@@ -132,9 +125,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) | |||
132 | break; | 125 | break; |
133 | next: | 126 | next: |
134 | spin_unlock(&head->lock); | 127 | spin_unlock(&head->lock); |
128 | if (++rover > high) | ||
129 | rover = low; | ||
135 | } while (--remaining > 0); | 130 | } while (--remaining > 0); |
136 | tcp_hashinfo.port_rover = rover; | ||
137 | spin_unlock(&tcp_hashinfo.portalloc_lock); | ||
138 | 131 | ||
139 | /* Exhausted local port range during search? It is not | 132 | /* Exhausted local port range during search? It is not |
140 | * possible for us to be holding one of the bind hash | 133 | * possible for us to be holding one of the bind hash |