diff options
Diffstat (limited to 'net/ipv6')
36 files changed, 2280 insertions, 1415 deletions
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 24f3aa0f2a35..ae14617e607f 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -16,6 +16,7 @@ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | |||
16 | ipv6-$(CONFIG_NETFILTER) += netfilter.o | 16 | ipv6-$(CONFIG_NETFILTER) += netfilter.o |
17 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o | 17 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o |
18 | ipv6-$(CONFIG_PROC_FS) += proc.o | 18 | ipv6-$(CONFIG_PROC_FS) += proc.o |
19 | ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o | ||
19 | 20 | ||
20 | ipv6-objs += $(ipv6-y) | 21 | ipv6-objs += $(ipv6-y) |
21 | 22 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 101e0e70ba27..5ab9973571ef 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -335,7 +335,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
335 | 335 | ||
336 | rwlock_init(&ndev->lock); | 336 | rwlock_init(&ndev->lock); |
337 | ndev->dev = dev; | 337 | ndev->dev = dev; |
338 | memcpy(&ndev->cnf, dev->nd_net->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 338 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
339 | ndev->cnf.mtu6 = dev->mtu; | 339 | ndev->cnf.mtu6 = dev->mtu; |
340 | ndev->cnf.sysctl = NULL; | 340 | ndev->cnf.sysctl = NULL; |
341 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | 341 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); |
@@ -349,7 +349,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
349 | if (snmp6_alloc_dev(ndev) < 0) { | 349 | if (snmp6_alloc_dev(ndev) < 0) { |
350 | ADBG((KERN_WARNING | 350 | ADBG((KERN_WARNING |
351 | "%s(): cannot allocate memory for statistics; dev=%s.\n", | 351 | "%s(): cannot allocate memory for statistics; dev=%s.\n", |
352 | __FUNCTION__, dev->name)); | 352 | __func__, dev->name)); |
353 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 353 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
354 | ndev->dead = 1; | 354 | ndev->dead = 1; |
355 | in6_dev_finish_destroy(ndev); | 355 | in6_dev_finish_destroy(ndev); |
@@ -359,7 +359,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
359 | if (snmp6_register_dev(ndev) < 0) { | 359 | if (snmp6_register_dev(ndev) < 0) { |
360 | ADBG((KERN_WARNING | 360 | ADBG((KERN_WARNING |
361 | "%s(): cannot create /proc/net/dev_snmp6/%s\n", | 361 | "%s(): cannot create /proc/net/dev_snmp6/%s\n", |
362 | __FUNCTION__, dev->name)); | 362 | __func__, dev->name)); |
363 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 363 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
364 | ndev->dead = 1; | 364 | ndev->dead = 1; |
365 | in6_dev_finish_destroy(ndev); | 365 | in6_dev_finish_destroy(ndev); |
@@ -493,7 +493,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
493 | dev_forward_change((struct inet6_dev *)table->extra1); | 493 | dev_forward_change((struct inet6_dev *)table->extra1); |
494 | 494 | ||
495 | if (*p) | 495 | if (*p) |
496 | rt6_purge_dflt_routers(); | 496 | rt6_purge_dflt_routers(net); |
497 | } | 497 | } |
498 | #endif | 498 | #endif |
499 | 499 | ||
@@ -561,7 +561,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
561 | write_lock(&addrconf_hash_lock); | 561 | write_lock(&addrconf_hash_lock); |
562 | 562 | ||
563 | /* Ignore adding duplicate addresses on an interface */ | 563 | /* Ignore adding duplicate addresses on an interface */ |
564 | if (ipv6_chk_same_addr(&init_net, addr, idev->dev)) { | 564 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
565 | ADBG(("ipv6_add_addr: already assigned\n")); | 565 | ADBG(("ipv6_add_addr: already assigned\n")); |
566 | err = -EEXIST; | 566 | err = -EEXIST; |
567 | goto out; | 567 | goto out; |
@@ -751,9 +751,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
751 | if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { | 751 | if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { |
752 | struct in6_addr prefix; | 752 | struct in6_addr prefix; |
753 | struct rt6_info *rt; | 753 | struct rt6_info *rt; |
754 | 754 | struct net *net = dev_net(ifp->idev->dev); | |
755 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); | 755 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); |
756 | rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1); | 756 | rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); |
757 | 757 | ||
758 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 758 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { |
759 | if (onlink == 0) { | 759 | if (onlink == 0) { |
@@ -877,20 +877,40 @@ 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 | unsigned int prefs; |
913 | }; | ||
894 | 914 | ||
895 | static inline int ipv6_saddr_preferred(int type) | 915 | static inline int ipv6_saddr_preferred(int type) |
896 | { | 916 | { |
@@ -900,27 +920,152 @@ static inline int ipv6_saddr_preferred(int type) | |||
900 | return 0; | 920 | return 0; |
901 | } | 921 | } |
902 | 922 | ||
903 | int ipv6_dev_get_saddr(struct net_device *daddr_dev, | 923 | static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, |
904 | struct in6_addr *daddr, struct in6_addr *saddr) | 924 | struct ipv6_saddr_dst *dst, |
925 | int i) | ||
905 | { | 926 | { |
906 | struct ipv6_saddr_score hiscore; | 927 | int ret; |
907 | struct inet6_ifaddr *ifa_result = NULL; | 928 | |
908 | int daddr_type = __ipv6_addr_type(daddr); | 929 | if (i <= score->rule) { |
909 | int daddr_scope = __ipv6_addr_src_scope(daddr_type); | 930 | switch (i) { |
910 | int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0; | 931 | case IPV6_SADDR_RULE_SCOPE: |
911 | u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex); | 932 | ret = score->scopedist; |
933 | break; | ||
934 | case IPV6_SADDR_RULE_PREFIX: | ||
935 | ret = score->matchlen; | ||
936 | break; | ||
937 | default: | ||
938 | ret = !!test_bit(i, score->scorebits); | ||
939 | } | ||
940 | goto out; | ||
941 | } | ||
942 | |||
943 | switch (i) { | ||
944 | case IPV6_SADDR_RULE_INIT: | ||
945 | /* Rule 0: remember if hiscore is not ready yet */ | ||
946 | ret = !!score->ifa; | ||
947 | break; | ||
948 | case IPV6_SADDR_RULE_LOCAL: | ||
949 | /* Rule 1: Prefer same address */ | ||
950 | ret = ipv6_addr_equal(&score->ifa->addr, dst->addr); | ||
951 | break; | ||
952 | case IPV6_SADDR_RULE_SCOPE: | ||
953 | /* Rule 2: Prefer appropriate scope | ||
954 | * | ||
955 | * ret | ||
956 | * ^ | ||
957 | * -1 | d 15 | ||
958 | * ---+--+-+---> scope | ||
959 | * | | ||
960 | * | d is scope of the destination. | ||
961 | * B-d | \ | ||
962 | * | \ <- smaller scope is better if | ||
963 | * B-15 | \ if scope is enough for destinaion. | ||
964 | * | ret = B - scope (-1 <= scope >= d <= 15). | ||
965 | * d-C-1 | / | ||
966 | * |/ <- greater is better | ||
967 | * -C / if scope is not enough for destination. | ||
968 | * /| ret = scope - C (-1 <= d < scope <= 15). | ||
969 | * | ||
970 | * d - C - 1 < B -15 (for all -1 <= d <= 15). | ||
971 | * C > d + 14 - B >= 15 + 14 - B = 29 - B. | ||
972 | * Assume B = 0 and we get C > 29. | ||
973 | */ | ||
974 | ret = __ipv6_addr_src_scope(score->addr_type); | ||
975 | if (ret >= dst->scope) | ||
976 | ret = -ret; | ||
977 | else | ||
978 | ret -= 128; /* 30 is enough */ | ||
979 | score->scopedist = ret; | ||
980 | break; | ||
981 | case IPV6_SADDR_RULE_PREFERRED: | ||
982 | /* Rule 3: Avoid deprecated and optimistic addresses */ | ||
983 | ret = ipv6_saddr_preferred(score->addr_type) || | ||
984 | !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)); | ||
985 | break; | ||
986 | #ifdef CONFIG_IPV6_MIP6 | ||
987 | case IPV6_SADDR_RULE_HOA: | ||
988 | { | ||
989 | /* Rule 4: Prefer home address */ | ||
990 | int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA); | ||
991 | ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome; | ||
992 | break; | ||
993 | } | ||
994 | #endif | ||
995 | case IPV6_SADDR_RULE_OIF: | ||
996 | /* Rule 5: Prefer outgoing interface */ | ||
997 | ret = (!dst->ifindex || | ||
998 | dst->ifindex == score->ifa->idev->dev->ifindex); | ||
999 | break; | ||
1000 | case IPV6_SADDR_RULE_LABEL: | ||
1001 | /* Rule 6: Prefer matching label */ | ||
1002 | ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, | ||
1003 | score->ifa->idev->dev->ifindex) == dst->label; | ||
1004 | break; | ||
1005 | #ifdef CONFIG_IPV6_PRIVACY | ||
1006 | case IPV6_SADDR_RULE_PRIVACY: | ||
1007 | { | ||
1008 | /* Rule 7: Prefer public address | ||
1009 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
1010 | */ | ||
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; | ||
1015 | break; | ||
1016 | } | ||
1017 | #endif | ||
1018 | case IPV6_SADDR_RULE_ORCHID: | ||
1019 | /* Rule 8-: Prefer ORCHID vs ORCHID or | ||
1020 | * non-ORCHID vs non-ORCHID | ||
1021 | */ | ||
1022 | ret = !(ipv6_addr_orchid(&score->ifa->addr) ^ | ||
1023 | ipv6_addr_orchid(dst->addr)); | ||
1024 | break; | ||
1025 | case IPV6_SADDR_RULE_PREFIX: | ||
1026 | /* Rule 8: Use longest matching prefix */ | ||
1027 | score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr, | ||
1028 | dst->addr); | ||
1029 | break; | ||
1030 | default: | ||
1031 | ret = 0; | ||
1032 | } | ||
1033 | |||
1034 | if (ret) | ||
1035 | __set_bit(i, score->scorebits); | ||
1036 | score->rule = i; | ||
1037 | out: | ||
1038 | return ret; | ||
1039 | } | ||
1040 | |||
1041 | int ipv6_dev_get_saddr(struct net_device *dst_dev, | ||
1042 | struct in6_addr *daddr, unsigned int prefs, | ||
1043 | struct in6_addr *saddr) | ||
1044 | { | ||
1045 | struct ipv6_saddr_score scores[2], | ||
1046 | *score = &scores[0], *hiscore = &scores[1]; | ||
1047 | struct net *net = dev_net(dst_dev); | ||
1048 | struct ipv6_saddr_dst dst; | ||
912 | struct net_device *dev; | 1049 | struct net_device *dev; |
1050 | int dst_type; | ||
1051 | |||
1052 | dst_type = __ipv6_addr_type(daddr); | ||
1053 | dst.addr = daddr; | ||
1054 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; | ||
1055 | dst.scope = __ipv6_addr_src_scope(dst_type); | ||
1056 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); | ||
1057 | dst.prefs = prefs; | ||
913 | 1058 | ||
914 | memset(&hiscore, 0, sizeof(hiscore)); | 1059 | hiscore->rule = -1; |
1060 | hiscore->ifa = NULL; | ||
915 | 1061 | ||
916 | read_lock(&dev_base_lock); | 1062 | read_lock(&dev_base_lock); |
917 | rcu_read_lock(); | 1063 | rcu_read_lock(); |
918 | 1064 | ||
919 | for_each_netdev(&init_net, dev) { | 1065 | for_each_netdev(net, dev) { |
920 | struct inet6_dev *idev; | 1066 | struct inet6_dev *idev; |
921 | struct inet6_ifaddr *ifa; | ||
922 | 1067 | ||
923 | /* Rule 0: Candidate Source Address (section 4) | 1068 | /* Candidate Source Address (section 4) |
924 | * - multicast and link-local destination address, | 1069 | * - multicast and link-local destination address, |
925 | * the set of candidate source address MUST only | 1070 | * the set of candidate source address MUST only |
926 | * include addresses assigned to interfaces | 1071 | * include addresses assigned to interfaces |
@@ -932,9 +1077,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
932 | * belonging to the same site as the outgoing | 1077 | * belonging to the same site as the outgoing |
933 | * interface.) | 1078 | * interface.) |
934 | */ | 1079 | */ |
935 | if ((daddr_type & IPV6_ADDR_MULTICAST || | 1080 | if (((dst_type & IPV6_ADDR_MULTICAST) || |
936 | daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && | 1081 | dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && |
937 | daddr_dev && dev != daddr_dev) | 1082 | dst.ifindex && dev->ifindex != dst.ifindex) |
938 | continue; | 1083 | continue; |
939 | 1084 | ||
940 | idev = __in6_dev_get(dev); | 1085 | idev = __in6_dev_get(dev); |
@@ -942,12 +1087,10 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
942 | continue; | 1087 | continue; |
943 | 1088 | ||
944 | read_lock_bh(&idev->lock); | 1089 | read_lock_bh(&idev->lock); |
945 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1090 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { |
946 | struct ipv6_saddr_score score; | 1091 | int i; |
947 | |||
948 | score.addr_type = __ipv6_addr_type(&ifa->addr); | ||
949 | 1092 | ||
950 | /* Rule 0: | 1093 | /* |
951 | * - Tentative Address (RFC2462 section 5.4) | 1094 | * - Tentative Address (RFC2462 section 5.4) |
952 | * - A tentative address is not considered | 1095 | * - A tentative address is not considered |
953 | * "assigned to an interface" in the traditional | 1096 | * "assigned to an interface" in the traditional |
@@ -957,11 +1100,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
957 | * addresses, and the unspecified address MUST | 1100 | * addresses, and the unspecified address MUST |
958 | * NOT be included in a candidate set. | 1101 | * NOT be included in a candidate set. |
959 | */ | 1102 | */ |
960 | if ((ifa->flags & IFA_F_TENTATIVE) && | 1103 | if ((score->ifa->flags & IFA_F_TENTATIVE) && |
961 | (!(ifa->flags & IFA_F_OPTIMISTIC))) | 1104 | (!(score->ifa->flags & IFA_F_OPTIMISTIC))) |
962 | continue; | 1105 | continue; |
963 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 1106 | |
964 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 1107 | score->addr_type = __ipv6_addr_type(&score->ifa->addr); |
1108 | |||
1109 | if (unlikely(score->addr_type == IPV6_ADDR_ANY || | ||
1110 | score->addr_type & IPV6_ADDR_MULTICAST)) { | ||
965 | LIMIT_NETDEBUG(KERN_DEBUG | 1111 | LIMIT_NETDEBUG(KERN_DEBUG |
966 | "ADDRCONF: unspecified / multicast address " | 1112 | "ADDRCONF: unspecified / multicast address " |
967 | "assigned as unicast address on %s", | 1113 | "assigned as unicast address on %s", |
@@ -969,207 +1115,63 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
969 | continue; | 1115 | continue; |
970 | } | 1116 | } |
971 | 1117 | ||
972 | score.attrs = 0; | 1118 | score->rule = -1; |
973 | score.matchlen = 0; | 1119 | bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); |
974 | score.scope = 0; | 1120 | |
975 | score.rule = 0; | 1121 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { |
976 | 1122 | int minihiscore, miniscore; | |
977 | if (ifa_result == NULL) { | 1123 | |
978 | /* record it if the first available entry */ | 1124 | minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); |
979 | goto record_it; | 1125 | miniscore = ipv6_get_saddr_eval(score, &dst, i); |
980 | } | 1126 | |
981 | 1127 | if (minihiscore > miniscore) { | |
982 | /* Rule 1: Prefer same address */ | 1128 | if (i == IPV6_SADDR_RULE_SCOPE && |
983 | if (hiscore.rule < 1) { | 1129 | score->scopedist > 0) { |
984 | if (ipv6_addr_equal(&ifa_result->addr, daddr)) | 1130 | /* |
985 | hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL; | 1131 | * special case: |
986 | hiscore.rule++; | 1132 | * each remaining entry |
987 | } | 1133 | * has too small (not enough) |
988 | if (ipv6_addr_equal(&ifa->addr, daddr)) { | 1134 | * scope, because ifa entries |
989 | score.attrs |= IPV6_SADDR_SCORE_LOCAL; | 1135 | * are sorted by their scope |
990 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) { | 1136 | * values. |
991 | score.rule = 1; | 1137 | */ |
992 | goto record_it; | 1138 | goto try_nextdev; |
993 | } | 1139 | } |
994 | } else { | 1140 | break; |
995 | if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL) | 1141 | } else if (minihiscore < miniscore) { |
996 | continue; | 1142 | struct ipv6_saddr_score *tmp; |
997 | } | ||
998 | |||
999 | /* Rule 2: Prefer appropriate scope */ | ||
1000 | if (hiscore.rule < 2) { | ||
1001 | hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type); | ||
1002 | hiscore.rule++; | ||
1003 | } | ||
1004 | score.scope = __ipv6_addr_src_scope(score.addr_type); | ||
1005 | if (hiscore.scope < score.scope) { | ||
1006 | if (hiscore.scope < daddr_scope) { | ||
1007 | score.rule = 2; | ||
1008 | goto record_it; | ||
1009 | } else | ||
1010 | continue; | ||
1011 | } else if (score.scope < hiscore.scope) { | ||
1012 | if (score.scope < daddr_scope) | ||
1013 | break; /* addresses sorted by scope */ | ||
1014 | else { | ||
1015 | score.rule = 2; | ||
1016 | goto record_it; | ||
1017 | } | ||
1018 | } | ||
1019 | 1143 | ||
1020 | /* Rule 3: Avoid deprecated and optimistic addresses */ | 1144 | if (hiscore->ifa) |
1021 | if (hiscore.rule < 3) { | 1145 | in6_ifa_put(hiscore->ifa); |
1022 | if (ipv6_saddr_preferred(hiscore.addr_type) || | ||
1023 | (((ifa_result->flags & | ||
1024 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) | ||
1025 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
1026 | hiscore.rule++; | ||
1027 | } | ||
1028 | if (ipv6_saddr_preferred(score.addr_type) || | ||
1029 | (((ifa->flags & | ||
1030 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { | ||
1031 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
1032 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { | ||
1033 | score.rule = 3; | ||
1034 | goto record_it; | ||
1035 | } | ||
1036 | } else { | ||
1037 | if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED) | ||
1038 | continue; | ||
1039 | } | ||
1040 | 1146 | ||
1041 | /* Rule 4: Prefer home address */ | 1147 | in6_ifa_hold(score->ifa); |
1042 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
1043 | if (hiscore.rule < 4) { | ||
1044 | if (ifa_result->flags & IFA_F_HOMEADDRESS) | ||
1045 | hiscore.attrs |= IPV6_SADDR_SCORE_HOA; | ||
1046 | hiscore.rule++; | ||
1047 | } | ||
1048 | if (ifa->flags & IFA_F_HOMEADDRESS) { | ||
1049 | score.attrs |= IPV6_SADDR_SCORE_HOA; | ||
1050 | if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) { | ||
1051 | score.rule = 4; | ||
1052 | goto record_it; | ||
1053 | } | ||
1054 | } else { | ||
1055 | if (hiscore.attrs & IPV6_SADDR_SCORE_HOA) | ||
1056 | continue; | ||
1057 | } | ||
1058 | #else | ||
1059 | if (hiscore.rule < 4) | ||
1060 | hiscore.rule++; | ||
1061 | #endif | ||
1062 | 1148 | ||
1063 | /* Rule 5: Prefer outgoing interface */ | 1149 | tmp = hiscore; |
1064 | if (hiscore.rule < 5) { | 1150 | hiscore = score; |
1065 | if (daddr_dev == NULL || | 1151 | score = tmp; |
1066 | daddr_dev == ifa_result->idev->dev) | ||
1067 | hiscore.attrs |= IPV6_SADDR_SCORE_OIF; | ||
1068 | hiscore.rule++; | ||
1069 | } | ||
1070 | if (daddr_dev == NULL || | ||
1071 | daddr_dev == ifa->idev->dev) { | ||
1072 | score.attrs |= IPV6_SADDR_SCORE_OIF; | ||
1073 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) { | ||
1074 | score.rule = 5; | ||
1075 | goto record_it; | ||
1076 | } | ||
1077 | } else { | ||
1078 | if (hiscore.attrs & IPV6_SADDR_SCORE_OIF) | ||
1079 | continue; | ||
1080 | } | ||
1081 | 1152 | ||
1082 | /* Rule 6: Prefer matching label */ | 1153 | /* restore our iterator */ |
1083 | if (hiscore.rule < 6) { | 1154 | score->ifa = hiscore->ifa; |
1084 | if (ipv6_addr_label(&ifa_result->addr, | ||
1085 | hiscore.addr_type, | ||
1086 | ifa_result->idev->dev->ifindex) == daddr_label) | ||
1087 | hiscore.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
1088 | hiscore.rule++; | ||
1089 | } | ||
1090 | if (ipv6_addr_label(&ifa->addr, | ||
1091 | score.addr_type, | ||
1092 | ifa->idev->dev->ifindex) == daddr_label) { | ||
1093 | score.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
1094 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) { | ||
1095 | score.rule = 6; | ||
1096 | goto record_it; | ||
1097 | } | ||
1098 | } else { | ||
1099 | if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL) | ||
1100 | continue; | ||
1101 | } | ||
1102 | 1155 | ||
1103 | #ifdef CONFIG_IPV6_PRIVACY | 1156 | break; |
1104 | /* Rule 7: Prefer public address | ||
1105 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
1106 | */ | ||
1107 | if (hiscore.rule < 7) { | ||
1108 | if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^ | ||
1109 | (ifa_result->idev->cnf.use_tempaddr >= 2)) | ||
1110 | hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
1111 | hiscore.rule++; | ||
1112 | } | ||
1113 | if ((!(ifa->flags & IFA_F_TEMPORARY)) ^ | ||
1114 | (ifa->idev->cnf.use_tempaddr >= 2)) { | ||
1115 | score.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
1116 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) { | ||
1117 | score.rule = 7; | ||
1118 | goto record_it; | ||
1119 | } | 1157 | } |
1120 | } else { | ||
1121 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) | ||
1122 | continue; | ||
1123 | } | ||
1124 | #else | ||
1125 | if (hiscore.rule < 7) | ||
1126 | hiscore.rule++; | ||
1127 | #endif | ||
1128 | /* Rule 8: Use longest matching prefix */ | ||
1129 | if (hiscore.rule < 8) { | ||
1130 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | ||
1131 | hiscore.rule++; | ||
1132 | } | ||
1133 | score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); | ||
1134 | if (score.matchlen > hiscore.matchlen) { | ||
1135 | score.rule = 8; | ||
1136 | goto record_it; | ||
1137 | } | 1158 | } |
1138 | #if 0 | ||
1139 | else if (score.matchlen < hiscore.matchlen) | ||
1140 | continue; | ||
1141 | #endif | ||
1142 | |||
1143 | /* Final Rule: choose first available one */ | ||
1144 | continue; | ||
1145 | record_it: | ||
1146 | if (ifa_result) | ||
1147 | in6_ifa_put(ifa_result); | ||
1148 | in6_ifa_hold(ifa); | ||
1149 | ifa_result = ifa; | ||
1150 | hiscore = score; | ||
1151 | } | 1159 | } |
1160 | try_nextdev: | ||
1152 | read_unlock_bh(&idev->lock); | 1161 | read_unlock_bh(&idev->lock); |
1153 | } | 1162 | } |
1154 | rcu_read_unlock(); | 1163 | rcu_read_unlock(); |
1155 | read_unlock(&dev_base_lock); | 1164 | read_unlock(&dev_base_lock); |
1156 | 1165 | ||
1157 | if (!ifa_result) | 1166 | if (!hiscore->ifa) |
1158 | return -EADDRNOTAVAIL; | 1167 | return -EADDRNOTAVAIL; |
1159 | 1168 | ||
1160 | ipv6_addr_copy(saddr, &ifa_result->addr); | 1169 | ipv6_addr_copy(saddr, &hiscore->ifa->addr); |
1161 | in6_ifa_put(ifa_result); | 1170 | in6_ifa_put(hiscore->ifa); |
1162 | return 0; | 1171 | return 0; |
1163 | } | 1172 | } |
1164 | 1173 | ||
1165 | 1174 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | |
1166 | int ipv6_get_saddr(struct dst_entry *dst, | ||
1167 | struct in6_addr *daddr, struct in6_addr *saddr) | ||
1168 | { | ||
1169 | return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr); | ||
1170 | } | ||
1171 | |||
1172 | EXPORT_SYMBOL(ipv6_get_saddr); | ||
1173 | 1175 | ||
1174 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1176 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
1175 | unsigned char banned_flags) | 1177 | unsigned char banned_flags) |
@@ -1215,7 +1217,7 @@ int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | |||
1215 | 1217 | ||
1216 | read_lock_bh(&addrconf_hash_lock); | 1218 | read_lock_bh(&addrconf_hash_lock); |
1217 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1219 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { |
1218 | if (ifp->idev->dev->nd_net != net) | 1220 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1219 | continue; | 1221 | continue; |
1220 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1222 | if (ipv6_addr_equal(&ifp->addr, addr) && |
1221 | !(ifp->flags&IFA_F_TENTATIVE)) { | 1223 | !(ifp->flags&IFA_F_TENTATIVE)) { |
@@ -1237,7 +1239,7 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1237 | u8 hash = ipv6_addr_hash(addr); | 1239 | u8 hash = ipv6_addr_hash(addr); |
1238 | 1240 | ||
1239 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1241 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { |
1240 | if (ifp->idev->dev->nd_net != net) | 1242 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1241 | continue; | 1243 | continue; |
1242 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1244 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1243 | if (dev == NULL || ifp->idev->dev == dev) | 1245 | if (dev == NULL || ifp->idev->dev == dev) |
@@ -1255,7 +1257,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr, | |||
1255 | 1257 | ||
1256 | read_lock_bh(&addrconf_hash_lock); | 1258 | read_lock_bh(&addrconf_hash_lock); |
1257 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1259 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { |
1258 | if (ifp->idev->dev->nd_net != net) | 1260 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1259 | continue; | 1261 | continue; |
1260 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1262 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1261 | if (dev == NULL || ifp->idev->dev == dev || | 1263 | if (dev == NULL || ifp->idev->dev == dev || |
@@ -1557,7 +1559,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
1557 | .fc_expires = expires, | 1559 | .fc_expires = expires, |
1558 | .fc_dst_len = plen, | 1560 | .fc_dst_len = plen, |
1559 | .fc_flags = RTF_UP | flags, | 1561 | .fc_flags = RTF_UP | flags, |
1560 | .fc_nlinfo.nl_net = &init_net, | 1562 | .fc_nlinfo.nl_net = dev_net(dev), |
1561 | }; | 1563 | }; |
1562 | 1564 | ||
1563 | ipv6_addr_copy(&cfg.fc_dst, pfx); | 1565 | ipv6_addr_copy(&cfg.fc_dst, pfx); |
@@ -1584,7 +1586,7 @@ static void addrconf_add_mroute(struct net_device *dev) | |||
1584 | .fc_ifindex = dev->ifindex, | 1586 | .fc_ifindex = dev->ifindex, |
1585 | .fc_dst_len = 8, | 1587 | .fc_dst_len = 8, |
1586 | .fc_flags = RTF_UP, | 1588 | .fc_flags = RTF_UP, |
1587 | .fc_nlinfo.nl_net = &init_net, | 1589 | .fc_nlinfo.nl_net = dev_net(dev), |
1588 | }; | 1590 | }; |
1589 | 1591 | ||
1590 | ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); | 1592 | ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); |
@@ -1601,7 +1603,7 @@ static void sit_route_add(struct net_device *dev) | |||
1601 | .fc_ifindex = dev->ifindex, | 1603 | .fc_ifindex = dev->ifindex, |
1602 | .fc_dst_len = 96, | 1604 | .fc_dst_len = 96, |
1603 | .fc_flags = RTF_UP | RTF_NONEXTHOP, | 1605 | .fc_flags = RTF_UP | RTF_NONEXTHOP, |
1604 | .fc_nlinfo.nl_net = &init_net, | 1606 | .fc_nlinfo.nl_net = dev_net(dev), |
1605 | }; | 1607 | }; |
1606 | 1608 | ||
1607 | /* prefix length - 96 bits "::d.d.d.d" */ | 1609 | /* prefix length - 96 bits "::d.d.d.d" */ |
@@ -1702,7 +1704,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1702 | 1704 | ||
1703 | if (pinfo->onlink) { | 1705 | if (pinfo->onlink) { |
1704 | struct rt6_info *rt; | 1706 | struct rt6_info *rt; |
1705 | rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1); | 1707 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, |
1708 | dev->ifindex, 1); | ||
1706 | 1709 | ||
1707 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 1710 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { |
1708 | if (rt->rt6i_flags&RTF_EXPIRES) { | 1711 | if (rt->rt6i_flags&RTF_EXPIRES) { |
@@ -1745,7 +1748,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1745 | 1748 | ||
1746 | ok: | 1749 | ok: |
1747 | 1750 | ||
1748 | ifp = ipv6_get_ifaddr(&init_net, &addr, dev, 1); | 1751 | ifp = ipv6_get_ifaddr(dev_net(dev), &addr, dev, 1); |
1749 | 1752 | ||
1750 | if (ifp == NULL && valid_lft) { | 1753 | if (ifp == NULL && valid_lft) { |
1751 | int max_addresses = in6_dev->cnf.max_addresses; | 1754 | int max_addresses = in6_dev->cnf.max_addresses; |
@@ -1868,7 +1871,7 @@ ok: | |||
1868 | * Special case for SIT interfaces where we create a new "virtual" | 1871 | * Special case for SIT interfaces where we create a new "virtual" |
1869 | * device. | 1872 | * device. |
1870 | */ | 1873 | */ |
1871 | int addrconf_set_dstaddr(void __user *arg) | 1874 | int addrconf_set_dstaddr(struct net *net, void __user *arg) |
1872 | { | 1875 | { |
1873 | struct in6_ifreq ireq; | 1876 | struct in6_ifreq ireq; |
1874 | struct net_device *dev; | 1877 | struct net_device *dev; |
@@ -1880,7 +1883,7 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1880 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) | 1883 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) |
1881 | goto err_exit; | 1884 | goto err_exit; |
1882 | 1885 | ||
1883 | dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex); | 1886 | dev = __dev_get_by_index(net, ireq.ifr6_ifindex); |
1884 | 1887 | ||
1885 | err = -ENODEV; | 1888 | err = -ENODEV; |
1886 | if (dev == NULL) | 1889 | if (dev == NULL) |
@@ -1911,7 +1914,8 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1911 | 1914 | ||
1912 | if (err == 0) { | 1915 | if (err == 0) { |
1913 | err = -ENOBUFS; | 1916 | err = -ENOBUFS; |
1914 | if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL) | 1917 | dev = __dev_get_by_name(net, p.name); |
1918 | if (!dev) | ||
1915 | goto err_exit; | 1919 | goto err_exit; |
1916 | err = dev_open(dev); | 1920 | err = dev_open(dev); |
1917 | } | 1921 | } |
@@ -1926,8 +1930,9 @@ err_exit: | |||
1926 | /* | 1930 | /* |
1927 | * Manual configuration of address on an interface | 1931 | * Manual configuration of address on an interface |
1928 | */ | 1932 | */ |
1929 | static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | 1933 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, |
1930 | __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft) | 1934 | int plen, __u8 ifa_flags, __u32 prefered_lft, |
1935 | __u32 valid_lft) | ||
1931 | { | 1936 | { |
1932 | struct inet6_ifaddr *ifp; | 1937 | struct inet6_ifaddr *ifp; |
1933 | struct inet6_dev *idev; | 1938 | struct inet6_dev *idev; |
@@ -1941,7 +1946,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1941 | if (!valid_lft || prefered_lft > valid_lft) | 1946 | if (!valid_lft || prefered_lft > valid_lft) |
1942 | return -EINVAL; | 1947 | return -EINVAL; |
1943 | 1948 | ||
1944 | if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL) | 1949 | dev = __dev_get_by_index(net, ifindex); |
1950 | if (!dev) | ||
1945 | return -ENODEV; | 1951 | return -ENODEV; |
1946 | 1952 | ||
1947 | if ((idev = addrconf_add_dev(dev)) == NULL) | 1953 | if ((idev = addrconf_add_dev(dev)) == NULL) |
@@ -1986,13 +1992,15 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1986 | return PTR_ERR(ifp); | 1992 | return PTR_ERR(ifp); |
1987 | } | 1993 | } |
1988 | 1994 | ||
1989 | static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) | 1995 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, |
1996 | int plen) | ||
1990 | { | 1997 | { |
1991 | struct inet6_ifaddr *ifp; | 1998 | struct inet6_ifaddr *ifp; |
1992 | struct inet6_dev *idev; | 1999 | struct inet6_dev *idev; |
1993 | struct net_device *dev; | 2000 | struct net_device *dev; |
1994 | 2001 | ||
1995 | if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL) | 2002 | dev = __dev_get_by_index(net, ifindex); |
2003 | if (!dev) | ||
1996 | return -ENODEV; | 2004 | return -ENODEV; |
1997 | 2005 | ||
1998 | if ((idev = __in6_dev_get(dev)) == NULL) | 2006 | if ((idev = __in6_dev_get(dev)) == NULL) |
@@ -2020,7 +2028,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) | |||
2020 | } | 2028 | } |
2021 | 2029 | ||
2022 | 2030 | ||
2023 | int addrconf_add_ifaddr(void __user *arg) | 2031 | int addrconf_add_ifaddr(struct net *net, void __user *arg) |
2024 | { | 2032 | { |
2025 | struct in6_ifreq ireq; | 2033 | struct in6_ifreq ireq; |
2026 | int err; | 2034 | int err; |
@@ -2032,13 +2040,14 @@ int addrconf_add_ifaddr(void __user *arg) | |||
2032 | return -EFAULT; | 2040 | return -EFAULT; |
2033 | 2041 | ||
2034 | rtnl_lock(); | 2042 | rtnl_lock(); |
2035 | err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, | 2043 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, |
2036 | IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 2044 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, |
2045 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | ||
2037 | rtnl_unlock(); | 2046 | rtnl_unlock(); |
2038 | return err; | 2047 | return err; |
2039 | } | 2048 | } |
2040 | 2049 | ||
2041 | int addrconf_del_ifaddr(void __user *arg) | 2050 | int addrconf_del_ifaddr(struct net *net, void __user *arg) |
2042 | { | 2051 | { |
2043 | struct in6_ifreq ireq; | 2052 | struct in6_ifreq ireq; |
2044 | int err; | 2053 | int err; |
@@ -2050,7 +2059,8 @@ int addrconf_del_ifaddr(void __user *arg) | |||
2050 | return -EFAULT; | 2059 | return -EFAULT; |
2051 | 2060 | ||
2052 | rtnl_lock(); | 2061 | rtnl_lock(); |
2053 | err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); | 2062 | err = inet6_addr_del(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, |
2063 | ireq.ifr6_prefixlen); | ||
2054 | rtnl_unlock(); | 2064 | rtnl_unlock(); |
2055 | return err; | 2065 | return err; |
2056 | } | 2066 | } |
@@ -2061,6 +2071,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2061 | struct inet6_ifaddr * ifp; | 2071 | struct inet6_ifaddr * ifp; |
2062 | struct in6_addr addr; | 2072 | struct in6_addr addr; |
2063 | struct net_device *dev; | 2073 | struct net_device *dev; |
2074 | struct net *net = dev_net(idev->dev); | ||
2064 | int scope; | 2075 | int scope; |
2065 | 2076 | ||
2066 | ASSERT_RTNL(); | 2077 | ASSERT_RTNL(); |
@@ -2087,7 +2098,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2087 | return; | 2098 | return; |
2088 | } | 2099 | } |
2089 | 2100 | ||
2090 | for_each_netdev(&init_net, dev) { | 2101 | for_each_netdev(net, dev) { |
2091 | struct in_device * in_dev = __in_dev_get_rtnl(dev); | 2102 | struct in_device * in_dev = __in_dev_get_rtnl(dev); |
2092 | if (in_dev && (dev->flags & IFF_UP)) { | 2103 | if (in_dev && (dev->flags & IFF_UP)) { |
2093 | struct in_ifaddr * ifa; | 2104 | struct in_ifaddr * ifa; |
@@ -2250,15 +2261,16 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | |||
2250 | static void ip6_tnl_add_linklocal(struct inet6_dev *idev) | 2261 | static void ip6_tnl_add_linklocal(struct inet6_dev *idev) |
2251 | { | 2262 | { |
2252 | struct net_device *link_dev; | 2263 | struct net_device *link_dev; |
2264 | struct net *net = dev_net(idev->dev); | ||
2253 | 2265 | ||
2254 | /* first try to inherit the link-local address from the link device */ | 2266 | /* first try to inherit the link-local address from the link device */ |
2255 | if (idev->dev->iflink && | 2267 | if (idev->dev->iflink && |
2256 | (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) { | 2268 | (link_dev = __dev_get_by_index(net, idev->dev->iflink))) { |
2257 | if (!ipv6_inherit_linklocal(idev, link_dev)) | 2269 | if (!ipv6_inherit_linklocal(idev, link_dev)) |
2258 | return; | 2270 | return; |
2259 | } | 2271 | } |
2260 | /* then try to inherit it from any device */ | 2272 | /* then try to inherit it from any device */ |
2261 | for_each_netdev(&init_net, link_dev) { | 2273 | for_each_netdev(net, link_dev) { |
2262 | if (!ipv6_inherit_linklocal(idev, link_dev)) | 2274 | if (!ipv6_inherit_linklocal(idev, link_dev)) |
2263 | return; | 2275 | return; |
2264 | } | 2276 | } |
@@ -2291,9 +2303,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2291 | int run_pending = 0; | 2303 | int run_pending = 0; |
2292 | int err; | 2304 | int err; |
2293 | 2305 | ||
2294 | if (dev->nd_net != &init_net) | ||
2295 | return NOTIFY_DONE; | ||
2296 | |||
2297 | switch(event) { | 2306 | switch(event) { |
2298 | case NETDEV_REGISTER: | 2307 | case NETDEV_REGISTER: |
2299 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2308 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
@@ -2433,6 +2442,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2433 | { | 2442 | { |
2434 | struct inet6_dev *idev; | 2443 | struct inet6_dev *idev; |
2435 | struct inet6_ifaddr *ifa, **bifa; | 2444 | struct inet6_ifaddr *ifa, **bifa; |
2445 | struct net *net = dev_net(dev); | ||
2436 | int i; | 2446 | int i; |
2437 | 2447 | ||
2438 | ASSERT_RTNL(); | 2448 | ASSERT_RTNL(); |
@@ -2440,7 +2450,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2440 | if (dev == init_net.loopback_dev && how == 1) | 2450 | if (dev == init_net.loopback_dev && how == 1) |
2441 | how = 0; | 2451 | how = 0; |
2442 | 2452 | ||
2443 | rt6_ifdown(dev); | 2453 | rt6_ifdown(net, dev); |
2444 | neigh_ifdown(&nd_tbl, dev); | 2454 | neigh_ifdown(&nd_tbl, dev); |
2445 | 2455 | ||
2446 | idev = __in6_dev_get(dev); | 2456 | idev = __in6_dev_get(dev); |
@@ -2756,12 +2766,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2756 | { | 2766 | { |
2757 | struct inet6_ifaddr *ifa = NULL; | 2767 | struct inet6_ifaddr *ifa = NULL; |
2758 | struct if6_iter_state *state = seq->private; | 2768 | struct if6_iter_state *state = seq->private; |
2759 | struct net *net = state->p.net; | 2769 | struct net *net = seq_file_net(seq); |
2760 | 2770 | ||
2761 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 2771 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2762 | ifa = inet6_addr_lst[state->bucket]; | 2772 | ifa = inet6_addr_lst[state->bucket]; |
2763 | 2773 | ||
2764 | while (ifa && ifa->idev->dev->nd_net != net) | 2774 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) |
2765 | ifa = ifa->lst_next; | 2775 | ifa = ifa->lst_next; |
2766 | if (ifa) | 2776 | if (ifa) |
2767 | break; | 2777 | break; |
@@ -2772,12 +2782,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2772 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 2782 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) |
2773 | { | 2783 | { |
2774 | struct if6_iter_state *state = seq->private; | 2784 | struct if6_iter_state *state = seq->private; |
2775 | struct net *net = state->p.net; | 2785 | struct net *net = seq_file_net(seq); |
2776 | 2786 | ||
2777 | ifa = ifa->lst_next; | 2787 | ifa = ifa->lst_next; |
2778 | try_again: | 2788 | try_again: |
2779 | if (ifa) { | 2789 | if (ifa) { |
2780 | if (ifa->idev->dev->nd_net != net) { | 2790 | if (!net_eq(dev_net(ifa->idev->dev), net)) { |
2781 | ifa = ifa->lst_next; | 2791 | ifa = ifa->lst_next; |
2782 | goto try_again; | 2792 | goto try_again; |
2783 | } | 2793 | } |
@@ -2895,7 +2905,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
2895 | u8 hash = ipv6_addr_hash(addr); | 2905 | u8 hash = ipv6_addr_hash(addr); |
2896 | read_lock_bh(&addrconf_hash_lock); | 2906 | read_lock_bh(&addrconf_hash_lock); |
2897 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 2907 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { |
2898 | if (ifp->idev->dev->nd_net != net) | 2908 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
2899 | continue; | 2909 | continue; |
2900 | if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && | 2910 | if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && |
2901 | (ifp->flags & IFA_F_HOMEADDRESS)) { | 2911 | (ifp->flags & IFA_F_HOMEADDRESS)) { |
@@ -3044,15 +3054,12 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = { | |||
3044 | static int | 3054 | static int |
3045 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 3055 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
3046 | { | 3056 | { |
3047 | struct net *net = skb->sk->sk_net; | 3057 | struct net *net = sock_net(skb->sk); |
3048 | struct ifaddrmsg *ifm; | 3058 | struct ifaddrmsg *ifm; |
3049 | struct nlattr *tb[IFA_MAX+1]; | 3059 | struct nlattr *tb[IFA_MAX+1]; |
3050 | struct in6_addr *pfx; | 3060 | struct in6_addr *pfx; |
3051 | int err; | 3061 | int err; |
3052 | 3062 | ||
3053 | if (net != &init_net) | ||
3054 | return -EINVAL; | ||
3055 | |||
3056 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3063 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3057 | if (err < 0) | 3064 | if (err < 0) |
3058 | return err; | 3065 | return err; |
@@ -3062,7 +3069,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3062 | if (pfx == NULL) | 3069 | if (pfx == NULL) |
3063 | return -EINVAL; | 3070 | return -EINVAL; |
3064 | 3071 | ||
3065 | return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); | 3072 | return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen); |
3066 | } | 3073 | } |
3067 | 3074 | ||
3068 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | 3075 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, |
@@ -3105,7 +3112,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
3105 | static int | 3112 | static int |
3106 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 3113 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
3107 | { | 3114 | { |
3108 | struct net *net = skb->sk->sk_net; | 3115 | struct net *net = sock_net(skb->sk); |
3109 | struct ifaddrmsg *ifm; | 3116 | struct ifaddrmsg *ifm; |
3110 | struct nlattr *tb[IFA_MAX+1]; | 3117 | struct nlattr *tb[IFA_MAX+1]; |
3111 | struct in6_addr *pfx; | 3118 | struct in6_addr *pfx; |
@@ -3115,9 +3122,6 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3115 | u8 ifa_flags; | 3122 | u8 ifa_flags; |
3116 | int err; | 3123 | int err; |
3117 | 3124 | ||
3118 | if (net != &init_net) | ||
3119 | return -EINVAL; | ||
3120 | |||
3121 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3125 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3122 | if (err < 0) | 3126 | if (err < 0) |
3123 | return err; | 3127 | return err; |
@@ -3138,7 +3142,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3138 | valid_lft = INFINITY_LIFE_TIME; | 3142 | valid_lft = INFINITY_LIFE_TIME; |
3139 | } | 3143 | } |
3140 | 3144 | ||
3141 | dev = __dev_get_by_index(&init_net, ifm->ifa_index); | 3145 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3142 | if (dev == NULL) | 3146 | if (dev == NULL) |
3143 | return -ENODEV; | 3147 | return -ENODEV; |
3144 | 3148 | ||
@@ -3151,8 +3155,9 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3151 | * It would be best to check for !NLM_F_CREATE here but | 3155 | * It would be best to check for !NLM_F_CREATE here but |
3152 | * userspace alreay relies on not having to provide this. | 3156 | * userspace alreay relies on not having to provide this. |
3153 | */ | 3157 | */ |
3154 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, | 3158 | return inet6_addr_add(net, ifm->ifa_index, pfx, |
3155 | ifa_flags, preferred_lft, valid_lft); | 3159 | ifm->ifa_prefixlen, ifa_flags, |
3160 | preferred_lft, valid_lft); | ||
3156 | } | 3161 | } |
3157 | 3162 | ||
3158 | if (nlh->nlmsg_flags & NLM_F_EXCL || | 3163 | if (nlh->nlmsg_flags & NLM_F_EXCL || |
@@ -3317,12 +3322,13 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3317 | struct inet6_ifaddr *ifa; | 3322 | struct inet6_ifaddr *ifa; |
3318 | struct ifmcaddr6 *ifmca; | 3323 | struct ifmcaddr6 *ifmca; |
3319 | struct ifacaddr6 *ifaca; | 3324 | struct ifacaddr6 *ifaca; |
3325 | struct net *net = sock_net(skb->sk); | ||
3320 | 3326 | ||
3321 | s_idx = cb->args[0]; | 3327 | s_idx = cb->args[0]; |
3322 | s_ip_idx = ip_idx = cb->args[1]; | 3328 | s_ip_idx = ip_idx = cb->args[1]; |
3323 | 3329 | ||
3324 | idx = 0; | 3330 | idx = 0; |
3325 | for_each_netdev(&init_net, dev) { | 3331 | for_each_netdev(net, dev) { |
3326 | if (idx < s_idx) | 3332 | if (idx < s_idx) |
3327 | goto cont; | 3333 | goto cont; |
3328 | if (idx > s_idx) | 3334 | if (idx > s_idx) |
@@ -3389,42 +3395,30 @@ cont: | |||
3389 | 3395 | ||
3390 | static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3396 | static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3391 | { | 3397 | { |
3392 | struct net *net = skb->sk->sk_net; | ||
3393 | enum addr_type_t type = UNICAST_ADDR; | 3398 | enum addr_type_t type = UNICAST_ADDR; |
3394 | 3399 | ||
3395 | if (net != &init_net) | ||
3396 | return 0; | ||
3397 | |||
3398 | return inet6_dump_addr(skb, cb, type); | 3400 | return inet6_dump_addr(skb, cb, type); |
3399 | } | 3401 | } |
3400 | 3402 | ||
3401 | static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3403 | static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3402 | { | 3404 | { |
3403 | struct net *net = skb->sk->sk_net; | ||
3404 | enum addr_type_t type = MULTICAST_ADDR; | 3405 | enum addr_type_t type = MULTICAST_ADDR; |
3405 | 3406 | ||
3406 | if (net != &init_net) | ||
3407 | return 0; | ||
3408 | |||
3409 | return inet6_dump_addr(skb, cb, type); | 3407 | return inet6_dump_addr(skb, cb, type); |
3410 | } | 3408 | } |
3411 | 3409 | ||
3412 | 3410 | ||
3413 | static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3411 | static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3414 | { | 3412 | { |
3415 | struct net *net = skb->sk->sk_net; | ||
3416 | enum addr_type_t type = ANYCAST_ADDR; | 3413 | enum addr_type_t type = ANYCAST_ADDR; |
3417 | 3414 | ||
3418 | if (net != &init_net) | ||
3419 | return 0; | ||
3420 | |||
3421 | return inet6_dump_addr(skb, cb, type); | 3415 | return inet6_dump_addr(skb, cb, type); |
3422 | } | 3416 | } |
3423 | 3417 | ||
3424 | static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | 3418 | static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, |
3425 | void *arg) | 3419 | void *arg) |
3426 | { | 3420 | { |
3427 | struct net *net = in_skb->sk->sk_net; | 3421 | struct net *net = sock_net(in_skb->sk); |
3428 | struct ifaddrmsg *ifm; | 3422 | struct ifaddrmsg *ifm; |
3429 | struct nlattr *tb[IFA_MAX+1]; | 3423 | struct nlattr *tb[IFA_MAX+1]; |
3430 | struct in6_addr *addr = NULL; | 3424 | struct in6_addr *addr = NULL; |
@@ -3433,9 +3427,6 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3433 | struct sk_buff *skb; | 3427 | struct sk_buff *skb; |
3434 | int err; | 3428 | int err; |
3435 | 3429 | ||
3436 | if (net != &init_net) | ||
3437 | return -EINVAL; | ||
3438 | |||
3439 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3430 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3440 | if (err < 0) | 3431 | if (err < 0) |
3441 | goto errout; | 3432 | goto errout; |
@@ -3448,7 +3439,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3448 | 3439 | ||
3449 | ifm = nlmsg_data(nlh); | 3440 | ifm = nlmsg_data(nlh); |
3450 | if (ifm->ifa_index) | 3441 | if (ifm->ifa_index) |
3451 | dev = __dev_get_by_index(&init_net, ifm->ifa_index); | 3442 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3452 | 3443 | ||
3453 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3444 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { |
3454 | err = -EADDRNOTAVAIL; | 3445 | err = -EADDRNOTAVAIL; |
@@ -3468,7 +3459,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3468 | kfree_skb(skb); | 3459 | kfree_skb(skb); |
3469 | goto errout_ifa; | 3460 | goto errout_ifa; |
3470 | } | 3461 | } |
3471 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 3462 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
3472 | errout_ifa: | 3463 | errout_ifa: |
3473 | in6_ifa_put(ifa); | 3464 | in6_ifa_put(ifa); |
3474 | errout: | 3465 | errout: |
@@ -3478,6 +3469,7 @@ errout: | |||
3478 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | 3469 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) |
3479 | { | 3470 | { |
3480 | struct sk_buff *skb; | 3471 | struct sk_buff *skb; |
3472 | struct net *net = dev_net(ifa->idev->dev); | ||
3481 | int err = -ENOBUFS; | 3473 | int err = -ENOBUFS; |
3482 | 3474 | ||
3483 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); | 3475 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); |
@@ -3491,10 +3483,10 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3491 | kfree_skb(skb); | 3483 | kfree_skb(skb); |
3492 | goto errout; | 3484 | goto errout; |
3493 | } | 3485 | } |
3494 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3486 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3495 | errout: | 3487 | errout: |
3496 | if (err < 0) | 3488 | if (err < 0) |
3497 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err); | 3489 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
3498 | } | 3490 | } |
3499 | 3491 | ||
3500 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | 3492 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, |
@@ -3653,18 +3645,15 @@ nla_put_failure: | |||
3653 | 3645 | ||
3654 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 3646 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
3655 | { | 3647 | { |
3656 | struct net *net = skb->sk->sk_net; | 3648 | struct net *net = sock_net(skb->sk); |
3657 | int idx, err; | 3649 | int idx, err; |
3658 | int s_idx = cb->args[0]; | 3650 | int s_idx = cb->args[0]; |
3659 | struct net_device *dev; | 3651 | struct net_device *dev; |
3660 | struct inet6_dev *idev; | 3652 | struct inet6_dev *idev; |
3661 | 3653 | ||
3662 | if (net != &init_net) | ||
3663 | return 0; | ||
3664 | |||
3665 | read_lock(&dev_base_lock); | 3654 | read_lock(&dev_base_lock); |
3666 | idx = 0; | 3655 | idx = 0; |
3667 | for_each_netdev(&init_net, dev) { | 3656 | for_each_netdev(net, dev) { |
3668 | if (idx < s_idx) | 3657 | if (idx < s_idx) |
3669 | goto cont; | 3658 | goto cont; |
3670 | if ((idev = in6_dev_get(dev)) == NULL) | 3659 | if ((idev = in6_dev_get(dev)) == NULL) |
@@ -3686,6 +3675,7 @@ cont: | |||
3686 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | 3675 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) |
3687 | { | 3676 | { |
3688 | struct sk_buff *skb; | 3677 | struct sk_buff *skb; |
3678 | struct net *net = dev_net(idev->dev); | ||
3689 | int err = -ENOBUFS; | 3679 | int err = -ENOBUFS; |
3690 | 3680 | ||
3691 | skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); | 3681 | skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); |
@@ -3699,10 +3689,10 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3699 | kfree_skb(skb); | 3689 | kfree_skb(skb); |
3700 | goto errout; | 3690 | goto errout; |
3701 | } | 3691 | } |
3702 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3692 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3703 | errout: | 3693 | errout: |
3704 | if (err < 0) | 3694 | if (err < 0) |
3705 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err); | 3695 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
3706 | } | 3696 | } |
3707 | 3697 | ||
3708 | static inline size_t inet6_prefix_nlmsg_size(void) | 3698 | static inline size_t inet6_prefix_nlmsg_size(void) |
@@ -3755,6 +3745,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3755 | struct prefix_info *pinfo) | 3745 | struct prefix_info *pinfo) |
3756 | { | 3746 | { |
3757 | struct sk_buff *skb; | 3747 | struct sk_buff *skb; |
3748 | struct net *net = dev_net(idev->dev); | ||
3758 | int err = -ENOBUFS; | 3749 | int err = -ENOBUFS; |
3759 | 3750 | ||
3760 | skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); | 3751 | skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); |
@@ -3768,10 +3759,10 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3768 | kfree_skb(skb); | 3759 | kfree_skb(skb); |
3769 | goto errout; | 3760 | goto errout; |
3770 | } | 3761 | } |
3771 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3762 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3772 | errout: | 3763 | errout: |
3773 | if (err < 0) | 3764 | if (err < 0) |
3774 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err); | 3765 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
3775 | } | 3766 | } |
3776 | 3767 | ||
3777 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 3768 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
@@ -4166,7 +4157,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev) | |||
4166 | NET_IPV6_NEIGH, "ipv6", | 4157 | NET_IPV6_NEIGH, "ipv6", |
4167 | &ndisc_ifinfo_sysctl_change, | 4158 | &ndisc_ifinfo_sysctl_change, |
4168 | NULL); | 4159 | NULL); |
4169 | __addrconf_sysctl_register(idev->dev->nd_net, idev->dev->name, | 4160 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, |
4170 | idev->dev->ifindex, idev, &idev->cnf); | 4161 | idev->dev->ifindex, idev, &idev->cnf); |
4171 | } | 4162 | } |
4172 | 4163 | ||
@@ -4261,6 +4252,32 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
4261 | 4252 | ||
4262 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4253 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4263 | 4254 | ||
4255 | |||
4256 | static int addrconf_net_init(struct net *net) | ||
4257 | { | ||
4258 | return 0; | ||
4259 | } | ||
4260 | |||
4261 | static void addrconf_net_exit(struct net *net) | ||
4262 | { | ||
4263 | struct net_device *dev; | ||
4264 | |||
4265 | rtnl_lock(); | ||
4266 | /* clean dev list */ | ||
4267 | for_each_netdev(net, dev) { | ||
4268 | if (__in6_dev_get(dev) == NULL) | ||
4269 | continue; | ||
4270 | addrconf_ifdown(dev, 1); | ||
4271 | } | ||
4272 | addrconf_ifdown(net->loopback_dev, 2); | ||
4273 | rtnl_unlock(); | ||
4274 | } | ||
4275 | |||
4276 | static struct pernet_operations addrconf_net_ops = { | ||
4277 | .init = addrconf_net_init, | ||
4278 | .exit = addrconf_net_exit, | ||
4279 | }; | ||
4280 | |||
4264 | /* | 4281 | /* |
4265 | * Init / cleanup code | 4282 | * Init / cleanup code |
4266 | */ | 4283 | */ |
@@ -4302,14 +4319,9 @@ int __init addrconf_init(void) | |||
4302 | if (err) | 4319 | if (err) |
4303 | goto errlo; | 4320 | goto errlo; |
4304 | 4321 | ||
4305 | ip6_null_entry.u.dst.dev = init_net.loopback_dev; | 4322 | err = register_pernet_device(&addrconf_net_ops); |
4306 | ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | 4323 | if (err) |
4307 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 4324 | return err; |
4308 | ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev; | ||
4309 | ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4310 | ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev; | ||
4311 | ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4312 | #endif | ||
4313 | 4325 | ||
4314 | register_netdevice_notifier(&ipv6_dev_notf); | 4326 | register_netdevice_notifier(&ipv6_dev_notf); |
4315 | 4327 | ||
@@ -4339,31 +4351,19 @@ errlo: | |||
4339 | 4351 | ||
4340 | void addrconf_cleanup(void) | 4352 | void addrconf_cleanup(void) |
4341 | { | 4353 | { |
4342 | struct net_device *dev; | ||
4343 | struct inet6_ifaddr *ifa; | 4354 | struct inet6_ifaddr *ifa; |
4344 | int i; | 4355 | int i; |
4345 | 4356 | ||
4346 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4357 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4358 | unregister_pernet_device(&addrconf_net_ops); | ||
4347 | 4359 | ||
4348 | unregister_pernet_subsys(&addrconf_ops); | 4360 | unregister_pernet_subsys(&addrconf_ops); |
4349 | 4361 | ||
4350 | rtnl_lock(); | 4362 | rtnl_lock(); |
4351 | 4363 | ||
4352 | /* | 4364 | /* |
4353 | * clean dev list. | ||
4354 | */ | ||
4355 | |||
4356 | for_each_netdev(&init_net, dev) { | ||
4357 | if (__in6_dev_get(dev) == NULL) | ||
4358 | continue; | ||
4359 | addrconf_ifdown(dev, 1); | ||
4360 | } | ||
4361 | addrconf_ifdown(init_net.loopback_dev, 2); | ||
4362 | |||
4363 | /* | ||
4364 | * Check hash table. | 4365 | * Check hash table. |
4365 | */ | 4366 | */ |
4366 | |||
4367 | write_lock_bh(&addrconf_hash_lock); | 4367 | write_lock_bh(&addrconf_hash_lock); |
4368 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4368 | for (i=0; i < IN6_ADDR_HSIZE; i++) { |
4369 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4369 | for (ifa=inet6_addr_lst[i]; ifa; ) { |
@@ -4380,6 +4380,7 @@ void addrconf_cleanup(void) | |||
4380 | write_unlock_bh(&addrconf_hash_lock); | 4380 | write_unlock_bh(&addrconf_hash_lock); |
4381 | 4381 | ||
4382 | del_timer(&addr_chk_timer); | 4382 | del_timer(&addr_chk_timer); |
4383 | |||
4384 | rtnl_unlock(); | 4383 | rtnl_unlock(); |
4384 | |||
4385 | unregister_pernet_subsys(&addrconf_net_ops); | ||
4385 | } | 4386 | } |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index a3c5a72218fd..9bfa8846f262 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -58,6 +58,7 @@ static struct ip6addrlbl_table | |||
58 | * ::ffff:0:0/96 V4MAPPED 4 | 58 | * ::ffff:0:0/96 V4MAPPED 4 |
59 | * fc00::/7 N/A 5 ULA (RFC 4193) | 59 | * fc00::/7 N/A 5 ULA (RFC 4193) |
60 | * 2001::/32 N/A 6 Teredo (RFC 4380) | 60 | * 2001::/32 N/A 6 Teredo (RFC 4380) |
61 | * 2001:10::/28 N/A 7 ORCHID (RFC 4843) | ||
61 | * | 62 | * |
62 | * Note: 0xffffffff is used if we do not have any policies. | 63 | * Note: 0xffffffff is used if we do not have any policies. |
63 | */ | 64 | */ |
@@ -85,6 +86,10 @@ static const __initdata struct ip6addrlbl_init_table | |||
85 | .prefix = &(struct in6_addr){{{ 0x20, 0x01 }}}, | 86 | .prefix = &(struct in6_addr){{{ 0x20, 0x01 }}}, |
86 | .prefixlen = 32, | 87 | .prefixlen = 32, |
87 | .label = 6, | 88 | .label = 6, |
89 | },{ /* 2001:10::/28 */ | ||
90 | .prefix = &(struct in6_addr){{{ 0x20, 0x01, 0x00, 0x10 }}}, | ||
91 | .prefixlen = 28, | ||
92 | .label = 7, | ||
88 | },{ /* ::ffff:0:0 */ | 93 | },{ /* ::ffff:0:0 */ |
89 | .prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}}, | 94 | .prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}}, |
90 | .prefixlen = 96, | 95 | .prefixlen = 96, |
@@ -161,7 +166,7 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | |||
161 | rcu_read_unlock(); | 166 | rcu_read_unlock(); |
162 | 167 | ||
163 | ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n", | 168 | ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n", |
164 | __FUNCTION__, | 169 | __func__, |
165 | NIP6(*addr), type, ifindex, | 170 | NIP6(*addr), type, ifindex, |
166 | label); | 171 | label); |
167 | 172 | ||
@@ -177,7 +182,7 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, | |||
177 | int addrtype; | 182 | int addrtype; |
178 | 183 | ||
179 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n", | 184 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n", |
180 | __FUNCTION__, | 185 | __func__, |
181 | NIP6(*prefix), prefixlen, | 186 | NIP6(*prefix), prefixlen, |
182 | ifindex, | 187 | ifindex, |
183 | (unsigned int)label); | 188 | (unsigned int)label); |
@@ -221,7 +226,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
221 | int ret = 0; | 226 | int ret = 0; |
222 | 227 | ||
223 | ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", | 228 | ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", |
224 | __FUNCTION__, | 229 | __func__, |
225 | newp, replace); | 230 | newp, replace); |
226 | 231 | ||
227 | if (hlist_empty(&ip6addrlbl_table.head)) { | 232 | if (hlist_empty(&ip6addrlbl_table.head)) { |
@@ -263,7 +268,7 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | |||
263 | int ret = 0; | 268 | int ret = 0; |
264 | 269 | ||
265 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n", | 270 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n", |
266 | __FUNCTION__, | 271 | __func__, |
267 | NIP6(*prefix), prefixlen, | 272 | NIP6(*prefix), prefixlen, |
268 | ifindex, | 273 | ifindex, |
269 | (unsigned int)label, | 274 | (unsigned int)label, |
@@ -289,7 +294,7 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
289 | int ret = -ESRCH; | 294 | int ret = -ESRCH; |
290 | 295 | ||
291 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", | 296 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", |
292 | __FUNCTION__, | 297 | __func__, |
293 | NIP6(*prefix), prefixlen, | 298 | NIP6(*prefix), prefixlen, |
294 | ifindex); | 299 | ifindex); |
295 | 300 | ||
@@ -313,7 +318,7 @@ static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
313 | int ret; | 318 | int ret; |
314 | 319 | ||
315 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", | 320 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", |
316 | __FUNCTION__, | 321 | __func__, |
317 | NIP6(*prefix), prefixlen, | 322 | NIP6(*prefix), prefixlen, |
318 | ifindex); | 323 | ifindex); |
319 | 324 | ||
@@ -330,7 +335,7 @@ static __init int ip6addrlbl_init(void) | |||
330 | int err = 0; | 335 | int err = 0; |
331 | int i; | 336 | int i; |
332 | 337 | ||
333 | ADDRLABEL(KERN_DEBUG "%s()\n", __FUNCTION__); | 338 | ADDRLABEL(KERN_DEBUG "%s()\n", __func__); |
334 | 339 | ||
335 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { | 340 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { |
336 | int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix, | 341 | int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix, |
@@ -359,7 +364,7 @@ static const struct nla_policy ifal_policy[IFAL_MAX+1] = { | |||
359 | static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | 364 | static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, |
360 | void *arg) | 365 | void *arg) |
361 | { | 366 | { |
362 | struct net *net = skb->sk->sk_net; | 367 | struct net *net = sock_net(skb->sk); |
363 | struct ifaddrlblmsg *ifal; | 368 | struct ifaddrlblmsg *ifal; |
364 | struct nlattr *tb[IFAL_MAX+1]; | 369 | struct nlattr *tb[IFAL_MAX+1]; |
365 | struct in6_addr *pfx; | 370 | struct in6_addr *pfx; |
@@ -447,7 +452,7 @@ static int ip6addrlbl_fill(struct sk_buff *skb, | |||
447 | 452 | ||
448 | static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) | 453 | static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) |
449 | { | 454 | { |
450 | struct net *net = skb->sk->sk_net; | 455 | struct net *net = sock_net(skb->sk); |
451 | struct ip6addrlbl_entry *p; | 456 | struct ip6addrlbl_entry *p; |
452 | struct hlist_node *pos; | 457 | struct hlist_node *pos; |
453 | int idx = 0, s_idx = cb->args[0]; | 458 | int idx = 0, s_idx = cb->args[0]; |
@@ -485,7 +490,7 @@ static inline int ip6addrlbl_msgsize(void) | |||
485 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | 490 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, |
486 | void *arg) | 491 | void *arg) |
487 | { | 492 | { |
488 | struct net *net = in_skb->sk->sk_net; | 493 | struct net *net = sock_net(in_skb->sk); |
489 | struct ifaddrlblmsg *ifal; | 494 | struct ifaddrlblmsg *ifal; |
490 | struct nlattr *tb[IFAL_MAX+1]; | 495 | struct nlattr *tb[IFAL_MAX+1]; |
491 | struct in6_addr *addr; | 496 | struct in6_addr *addr; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index f0aa97738746..1731b0abf7f5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -92,9 +92,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol) | |||
92 | int try_loading_module = 0; | 92 | int try_loading_module = 0; |
93 | int err; | 93 | int err; |
94 | 94 | ||
95 | if (net != &init_net) | ||
96 | return -EAFNOSUPPORT; | ||
97 | |||
98 | if (sock->type != SOCK_RAW && | 95 | if (sock->type != SOCK_RAW && |
99 | sock->type != SOCK_DGRAM && | 96 | sock->type != SOCK_DGRAM && |
100 | !inet_ehash_secret) | 97 | !inet_ehash_secret) |
@@ -248,6 +245,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
248 | struct sock *sk = sock->sk; | 245 | struct sock *sk = sock->sk; |
249 | struct inet_sock *inet = inet_sk(sk); | 246 | struct inet_sock *inet = inet_sk(sk); |
250 | struct ipv6_pinfo *np = inet6_sk(sk); | 247 | struct ipv6_pinfo *np = inet6_sk(sk); |
248 | struct net *net = sock_net(sk); | ||
251 | __be32 v4addr = 0; | 249 | __be32 v4addr = 0; |
252 | unsigned short snum; | 250 | unsigned short snum; |
253 | int addr_type = 0; | 251 | int addr_type = 0; |
@@ -278,7 +276,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
278 | /* Check if the address belongs to the host. */ | 276 | /* Check if the address belongs to the host. */ |
279 | if (addr_type == IPV6_ADDR_MAPPED) { | 277 | if (addr_type == IPV6_ADDR_MAPPED) { |
280 | v4addr = addr->sin6_addr.s6_addr32[3]; | 278 | v4addr = addr->sin6_addr.s6_addr32[3]; |
281 | if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) { | 279 | if (inet_addr_type(net, v4addr) != RTN_LOCAL) { |
282 | err = -EADDRNOTAVAIL; | 280 | err = -EADDRNOTAVAIL; |
283 | goto out; | 281 | goto out; |
284 | } | 282 | } |
@@ -300,7 +298,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
300 | err = -EINVAL; | 298 | err = -EINVAL; |
301 | goto out; | 299 | goto out; |
302 | } | 300 | } |
303 | dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); | 301 | dev = dev_get_by_index(net, sk->sk_bound_dev_if); |
304 | if (!dev) { | 302 | if (!dev) { |
305 | err = -ENODEV; | 303 | err = -ENODEV; |
306 | goto out; | 304 | goto out; |
@@ -312,7 +310,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
312 | */ | 310 | */ |
313 | v4addr = LOOPBACK4_IPV6; | 311 | v4addr = LOOPBACK4_IPV6; |
314 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 312 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
315 | if (!ipv6_chk_addr(&init_net, &addr->sin6_addr, | 313 | if (!ipv6_chk_addr(net, &addr->sin6_addr, |
316 | dev, 0)) { | 314 | dev, 0)) { |
317 | if (dev) | 315 | if (dev) |
318 | dev_put(dev); | 316 | dev_put(dev); |
@@ -440,6 +438,7 @@ EXPORT_SYMBOL(inet6_getname); | |||
440 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 438 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
441 | { | 439 | { |
442 | struct sock *sk = sock->sk; | 440 | struct sock *sk = sock->sk; |
441 | struct net *net = sock_net(sk); | ||
443 | 442 | ||
444 | switch(cmd) | 443 | switch(cmd) |
445 | { | 444 | { |
@@ -452,14 +451,14 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
452 | case SIOCADDRT: | 451 | case SIOCADDRT: |
453 | case SIOCDELRT: | 452 | case SIOCDELRT: |
454 | 453 | ||
455 | return(ipv6_route_ioctl(cmd,(void __user *)arg)); | 454 | return(ipv6_route_ioctl(net, cmd, (void __user *)arg)); |
456 | 455 | ||
457 | case SIOCSIFADDR: | 456 | case SIOCSIFADDR: |
458 | return addrconf_add_ifaddr((void __user *) arg); | 457 | return addrconf_add_ifaddr(net, (void __user *) arg); |
459 | case SIOCDIFADDR: | 458 | case SIOCDIFADDR: |
460 | return addrconf_del_ifaddr((void __user *) arg); | 459 | return addrconf_del_ifaddr(net, (void __user *) arg); |
461 | case SIOCSIFDSTADDR: | 460 | case SIOCSIFDSTADDR: |
462 | return addrconf_set_dstaddr((void __user *) arg); | 461 | return addrconf_set_dstaddr(net, (void __user *) arg); |
463 | default: | 462 | default: |
464 | if (!sk->sk_prot->ioctl) | 463 | if (!sk->sk_prot->ioctl) |
465 | return -ENOIOCTLCMD; | 464 | return -ENOIOCTLCMD; |
@@ -678,6 +677,129 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) | |||
678 | 677 | ||
679 | EXPORT_SYMBOL_GPL(ipv6_opt_accepted); | 678 | EXPORT_SYMBOL_GPL(ipv6_opt_accepted); |
680 | 679 | ||
680 | static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb, | ||
681 | int proto) | ||
682 | { | ||
683 | struct inet6_protocol *ops = NULL; | ||
684 | |||
685 | for (;;) { | ||
686 | struct ipv6_opt_hdr *opth; | ||
687 | int len; | ||
688 | |||
689 | if (proto != NEXTHDR_HOP) { | ||
690 | ops = rcu_dereference(inet6_protos[proto]); | ||
691 | |||
692 | if (unlikely(!ops)) | ||
693 | break; | ||
694 | |||
695 | if (!(ops->flags & INET6_PROTO_GSO_EXTHDR)) | ||
696 | break; | ||
697 | } | ||
698 | |||
699 | if (unlikely(!pskb_may_pull(skb, 8))) | ||
700 | break; | ||
701 | |||
702 | opth = (void *)skb->data; | ||
703 | len = ipv6_optlen(opth); | ||
704 | |||
705 | if (unlikely(!pskb_may_pull(skb, len))) | ||
706 | break; | ||
707 | |||
708 | proto = opth->nexthdr; | ||
709 | __skb_pull(skb, len); | ||
710 | } | ||
711 | |||
712 | return ops; | ||
713 | } | ||
714 | |||
715 | static int ipv6_gso_send_check(struct sk_buff *skb) | ||
716 | { | ||
717 | struct ipv6hdr *ipv6h; | ||
718 | struct inet6_protocol *ops; | ||
719 | int err = -EINVAL; | ||
720 | |||
721 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
722 | goto out; | ||
723 | |||
724 | ipv6h = ipv6_hdr(skb); | ||
725 | __skb_pull(skb, sizeof(*ipv6h)); | ||
726 | err = -EPROTONOSUPPORT; | ||
727 | |||
728 | rcu_read_lock(); | ||
729 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | ||
730 | if (likely(ops && ops->gso_send_check)) { | ||
731 | skb_reset_transport_header(skb); | ||
732 | err = ops->gso_send_check(skb); | ||
733 | } | ||
734 | rcu_read_unlock(); | ||
735 | |||
736 | out: | ||
737 | return err; | ||
738 | } | ||
739 | |||
740 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | ||
741 | { | ||
742 | struct sk_buff *segs = ERR_PTR(-EINVAL); | ||
743 | struct ipv6hdr *ipv6h; | ||
744 | struct inet6_protocol *ops; | ||
745 | |||
746 | if (!(features & NETIF_F_V6_CSUM)) | ||
747 | features &= ~NETIF_F_SG; | ||
748 | |||
749 | if (unlikely(skb_shinfo(skb)->gso_type & | ||
750 | ~(SKB_GSO_UDP | | ||
751 | SKB_GSO_DODGY | | ||
752 | SKB_GSO_TCP_ECN | | ||
753 | SKB_GSO_TCPV6 | | ||
754 | 0))) | ||
755 | goto out; | ||
756 | |||
757 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
758 | goto out; | ||
759 | |||
760 | ipv6h = ipv6_hdr(skb); | ||
761 | __skb_pull(skb, sizeof(*ipv6h)); | ||
762 | segs = ERR_PTR(-EPROTONOSUPPORT); | ||
763 | |||
764 | rcu_read_lock(); | ||
765 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | ||
766 | if (likely(ops && ops->gso_segment)) { | ||
767 | skb_reset_transport_header(skb); | ||
768 | segs = ops->gso_segment(skb, features); | ||
769 | } | ||
770 | rcu_read_unlock(); | ||
771 | |||
772 | if (unlikely(IS_ERR(segs))) | ||
773 | goto out; | ||
774 | |||
775 | for (skb = segs; skb; skb = skb->next) { | ||
776 | ipv6h = ipv6_hdr(skb); | ||
777 | ipv6h->payload_len = htons(skb->len - skb->mac_len - | ||
778 | sizeof(*ipv6h)); | ||
779 | } | ||
780 | |||
781 | out: | ||
782 | return segs; | ||
783 | } | ||
784 | |||
785 | static struct packet_type ipv6_packet_type = { | ||
786 | .type = __constant_htons(ETH_P_IPV6), | ||
787 | .func = ipv6_rcv, | ||
788 | .gso_send_check = ipv6_gso_send_check, | ||
789 | .gso_segment = ipv6_gso_segment, | ||
790 | }; | ||
791 | |||
792 | static int __init ipv6_packet_init(void) | ||
793 | { | ||
794 | dev_add_pack(&ipv6_packet_type); | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static void ipv6_packet_cleanup(void) | ||
799 | { | ||
800 | dev_remove_pack(&ipv6_packet_type); | ||
801 | } | ||
802 | |||
681 | static int __init init_ipv6_mibs(void) | 803 | static int __init init_ipv6_mibs(void) |
682 | { | 804 | { |
683 | if (snmp_mib_init((void **)ipv6_statistics, | 805 | if (snmp_mib_init((void **)ipv6_statistics, |
@@ -720,6 +842,8 @@ static void cleanup_ipv6_mibs(void) | |||
720 | 842 | ||
721 | static int inet6_net_init(struct net *net) | 843 | static int inet6_net_init(struct net *net) |
722 | { | 844 | { |
845 | int err = 0; | ||
846 | |||
723 | net->ipv6.sysctl.bindv6only = 0; | 847 | net->ipv6.sysctl.bindv6only = 0; |
724 | net->ipv6.sysctl.flush_delay = 0; | 848 | net->ipv6.sysctl.flush_delay = 0; |
725 | net->ipv6.sysctl.ip6_rt_max_size = 4096; | 849 | net->ipv6.sysctl.ip6_rt_max_size = 4096; |
@@ -731,12 +855,36 @@ static int inet6_net_init(struct net *net) | |||
731 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; | 855 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; |
732 | net->ipv6.sysctl.icmpv6_time = 1*HZ; | 856 | net->ipv6.sysctl.icmpv6_time = 1*HZ; |
733 | 857 | ||
734 | return 0; | 858 | #ifdef CONFIG_PROC_FS |
859 | err = udp6_proc_init(net); | ||
860 | if (err) | ||
861 | goto out; | ||
862 | err = tcp6_proc_init(net); | ||
863 | if (err) | ||
864 | goto proc_tcp6_fail; | ||
865 | err = ac6_proc_init(net); | ||
866 | if (err) | ||
867 | goto proc_ac6_fail; | ||
868 | out: | ||
869 | #endif | ||
870 | return err; | ||
871 | |||
872 | #ifdef CONFIG_PROC_FS | ||
873 | proc_ac6_fail: | ||
874 | tcp6_proc_exit(net); | ||
875 | proc_tcp6_fail: | ||
876 | udp6_proc_exit(net); | ||
877 | goto out; | ||
878 | #endif | ||
735 | } | 879 | } |
736 | 880 | ||
737 | static void inet6_net_exit(struct net *net) | 881 | static void inet6_net_exit(struct net *net) |
738 | { | 882 | { |
739 | return; | 883 | #ifdef CONFIG_PROC_FS |
884 | udp6_proc_exit(net); | ||
885 | tcp6_proc_exit(net); | ||
886 | ac6_proc_exit(net); | ||
887 | #endif | ||
740 | } | 888 | } |
741 | 889 | ||
742 | static struct pernet_operations inet6_net_ops = { | 890 | static struct pernet_operations inet6_net_ops = { |
@@ -802,19 +950,13 @@ static int __init inet6_init(void) | |||
802 | err = register_pernet_subsys(&inet6_net_ops); | 950 | err = register_pernet_subsys(&inet6_net_ops); |
803 | if (err) | 951 | if (err) |
804 | goto register_pernet_fail; | 952 | goto register_pernet_fail; |
805 | 953 | err = icmpv6_init(); | |
806 | #ifdef CONFIG_SYSCTL | ||
807 | err = ipv6_sysctl_register(); | ||
808 | if (err) | ||
809 | goto sysctl_fail; | ||
810 | #endif | ||
811 | err = icmpv6_init(&inet6_family_ops); | ||
812 | if (err) | 954 | if (err) |
813 | goto icmp_fail; | 955 | goto icmp_fail; |
814 | err = ndisc_init(&inet6_family_ops); | 956 | err = ndisc_init(); |
815 | if (err) | 957 | if (err) |
816 | goto ndisc_fail; | 958 | goto ndisc_fail; |
817 | err = igmp6_init(&inet6_family_ops); | 959 | err = igmp6_init(); |
818 | if (err) | 960 | if (err) |
819 | goto igmp_fail; | 961 | goto igmp_fail; |
820 | err = ipv6_netfilter_init(); | 962 | err = ipv6_netfilter_init(); |
@@ -825,17 +967,10 @@ static int __init inet6_init(void) | |||
825 | err = -ENOMEM; | 967 | err = -ENOMEM; |
826 | if (raw6_proc_init()) | 968 | if (raw6_proc_init()) |
827 | goto proc_raw6_fail; | 969 | goto proc_raw6_fail; |
828 | if (tcp6_proc_init()) | ||
829 | goto proc_tcp6_fail; | ||
830 | if (udp6_proc_init()) | ||
831 | goto proc_udp6_fail; | ||
832 | if (udplite6_proc_init()) | 970 | if (udplite6_proc_init()) |
833 | goto proc_udplite6_fail; | 971 | goto proc_udplite6_fail; |
834 | if (ipv6_misc_proc_init()) | 972 | if (ipv6_misc_proc_init()) |
835 | goto proc_misc6_fail; | 973 | goto proc_misc6_fail; |
836 | |||
837 | if (ac6_proc_init()) | ||
838 | goto proc_anycast6_fail; | ||
839 | if (if6_proc_init()) | 974 | if (if6_proc_init()) |
840 | goto proc_if6_fail; | 975 | goto proc_if6_fail; |
841 | #endif | 976 | #endif |
@@ -874,9 +1009,19 @@ static int __init inet6_init(void) | |||
874 | err = ipv6_packet_init(); | 1009 | err = ipv6_packet_init(); |
875 | if (err) | 1010 | if (err) |
876 | goto ipv6_packet_fail; | 1011 | goto ipv6_packet_fail; |
1012 | |||
1013 | #ifdef CONFIG_SYSCTL | ||
1014 | err = ipv6_sysctl_register(); | ||
1015 | if (err) | ||
1016 | goto sysctl_fail; | ||
1017 | #endif | ||
877 | out: | 1018 | out: |
878 | return err; | 1019 | return err; |
879 | 1020 | ||
1021 | #ifdef CONFIG_SYSCTL | ||
1022 | sysctl_fail: | ||
1023 | ipv6_packet_cleanup(); | ||
1024 | #endif | ||
880 | ipv6_packet_fail: | 1025 | ipv6_packet_fail: |
881 | tcpv6_exit(); | 1026 | tcpv6_exit(); |
882 | tcpv6_fail: | 1027 | tcpv6_fail: |
@@ -897,16 +1042,10 @@ ip6_route_fail: | |||
897 | #ifdef CONFIG_PROC_FS | 1042 | #ifdef CONFIG_PROC_FS |
898 | if6_proc_exit(); | 1043 | if6_proc_exit(); |
899 | proc_if6_fail: | 1044 | proc_if6_fail: |
900 | ac6_proc_exit(); | ||
901 | proc_anycast6_fail: | ||
902 | ipv6_misc_proc_exit(); | 1045 | ipv6_misc_proc_exit(); |
903 | proc_misc6_fail: | 1046 | proc_misc6_fail: |
904 | udplite6_proc_exit(); | 1047 | udplite6_proc_exit(); |
905 | proc_udplite6_fail: | 1048 | proc_udplite6_fail: |
906 | udp6_proc_exit(); | ||
907 | proc_udp6_fail: | ||
908 | tcp6_proc_exit(); | ||
909 | proc_tcp6_fail: | ||
910 | raw6_proc_exit(); | 1049 | raw6_proc_exit(); |
911 | proc_raw6_fail: | 1050 | proc_raw6_fail: |
912 | #endif | 1051 | #endif |
@@ -918,10 +1057,6 @@ igmp_fail: | |||
918 | ndisc_fail: | 1057 | ndisc_fail: |
919 | icmpv6_cleanup(); | 1058 | icmpv6_cleanup(); |
920 | icmp_fail: | 1059 | icmp_fail: |
921 | #ifdef CONFIG_SYSCTL | ||
922 | ipv6_sysctl_unregister(); | ||
923 | sysctl_fail: | ||
924 | #endif | ||
925 | unregister_pernet_subsys(&inet6_net_ops); | 1060 | unregister_pernet_subsys(&inet6_net_ops); |
926 | register_pernet_fail: | 1061 | register_pernet_fail: |
927 | cleanup_ipv6_mibs(); | 1062 | cleanup_ipv6_mibs(); |
@@ -949,6 +1084,9 @@ static void __exit inet6_exit(void) | |||
949 | /* Disallow any further netlink messages */ | 1084 | /* Disallow any further netlink messages */ |
950 | rtnl_unregister_all(PF_INET6); | 1085 | rtnl_unregister_all(PF_INET6); |
951 | 1086 | ||
1087 | #ifdef CONFIG_SYSCTL | ||
1088 | ipv6_sysctl_unregister(); | ||
1089 | #endif | ||
952 | udpv6_exit(); | 1090 | udpv6_exit(); |
953 | udplitev6_exit(); | 1091 | udplitev6_exit(); |
954 | tcpv6_exit(); | 1092 | tcpv6_exit(); |
@@ -964,11 +1102,8 @@ static void __exit inet6_exit(void) | |||
964 | 1102 | ||
965 | /* Cleanup code parts. */ | 1103 | /* Cleanup code parts. */ |
966 | if6_proc_exit(); | 1104 | if6_proc_exit(); |
967 | ac6_proc_exit(); | ||
968 | ipv6_misc_proc_exit(); | 1105 | ipv6_misc_proc_exit(); |
969 | udplite6_proc_exit(); | 1106 | udplite6_proc_exit(); |
970 | udp6_proc_exit(); | ||
971 | tcp6_proc_exit(); | ||
972 | raw6_proc_exit(); | 1107 | raw6_proc_exit(); |
973 | #endif | 1108 | #endif |
974 | ipv6_netfilter_fini(); | 1109 | ipv6_netfilter_fini(); |
@@ -976,9 +1111,7 @@ static void __exit inet6_exit(void) | |||
976 | ndisc_cleanup(); | 1111 | ndisc_cleanup(); |
977 | icmpv6_cleanup(); | 1112 | icmpv6_cleanup(); |
978 | rawv6_exit(); | 1113 | rawv6_exit(); |
979 | #ifdef CONFIG_SYSCTL | 1114 | |
980 | ipv6_sysctl_unregister(); | ||
981 | #endif | ||
982 | unregister_pernet_subsys(&inet6_net_ops); | 1115 | unregister_pernet_subsys(&inet6_net_ops); |
983 | cleanup_ipv6_mibs(); | 1116 | cleanup_ipv6_mibs(); |
984 | proto_unregister(&rawv6_prot); | 1117 | proto_unregister(&rawv6_prot); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 9c7f83fbc3a1..463bd95d6b13 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -82,6 +82,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
82 | struct net_device *dev = NULL; | 82 | struct net_device *dev = NULL; |
83 | struct inet6_dev *idev; | 83 | struct inet6_dev *idev; |
84 | struct ipv6_ac_socklist *pac; | 84 | struct ipv6_ac_socklist *pac; |
85 | struct net *net = sock_net(sk); | ||
85 | int ishost = !ipv6_devconf.forwarding; | 86 | int ishost = !ipv6_devconf.forwarding; |
86 | int err = 0; | 87 | int err = 0; |
87 | 88 | ||
@@ -89,7 +90,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
89 | return -EPERM; | 90 | return -EPERM; |
90 | if (ipv6_addr_is_multicast(addr)) | 91 | if (ipv6_addr_is_multicast(addr)) |
91 | return -EINVAL; | 92 | return -EINVAL; |
92 | if (ipv6_chk_addr(&init_net, addr, NULL, 0)) | 93 | if (ipv6_chk_addr(net, addr, NULL, 0)) |
93 | return -EINVAL; | 94 | return -EINVAL; |
94 | 95 | ||
95 | pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); | 96 | pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); |
@@ -101,7 +102,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
101 | if (ifindex == 0) { | 102 | if (ifindex == 0) { |
102 | struct rt6_info *rt; | 103 | struct rt6_info *rt; |
103 | 104 | ||
104 | rt = rt6_lookup(addr, NULL, 0, 0); | 105 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
105 | if (rt) { | 106 | if (rt) { |
106 | dev = rt->rt6i_dev; | 107 | dev = rt->rt6i_dev; |
107 | dev_hold(dev); | 108 | dev_hold(dev); |
@@ -112,10 +113,10 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
112 | } else { | 113 | } else { |
113 | /* router, no matching interface: just pick one */ | 114 | /* router, no matching interface: just pick one */ |
114 | 115 | ||
115 | dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK); | 116 | dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK); |
116 | } | 117 | } |
117 | } else | 118 | } else |
118 | dev = dev_get_by_index(&init_net, ifindex); | 119 | dev = dev_get_by_index(net, ifindex); |
119 | 120 | ||
120 | if (dev == NULL) { | 121 | if (dev == NULL) { |
121 | err = -ENODEV; | 122 | err = -ENODEV; |
@@ -176,6 +177,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
176 | struct ipv6_pinfo *np = inet6_sk(sk); | 177 | struct ipv6_pinfo *np = inet6_sk(sk); |
177 | struct net_device *dev; | 178 | struct net_device *dev; |
178 | struct ipv6_ac_socklist *pac, *prev_pac; | 179 | struct ipv6_ac_socklist *pac, *prev_pac; |
180 | struct net *net = sock_net(sk); | ||
179 | 181 | ||
180 | write_lock_bh(&ipv6_sk_ac_lock); | 182 | write_lock_bh(&ipv6_sk_ac_lock); |
181 | prev_pac = NULL; | 183 | prev_pac = NULL; |
@@ -196,7 +198,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
196 | 198 | ||
197 | write_unlock_bh(&ipv6_sk_ac_lock); | 199 | write_unlock_bh(&ipv6_sk_ac_lock); |
198 | 200 | ||
199 | dev = dev_get_by_index(&init_net, pac->acl_ifindex); | 201 | dev = dev_get_by_index(net, pac->acl_ifindex); |
200 | if (dev) { | 202 | if (dev) { |
201 | ipv6_dev_ac_dec(dev, &pac->acl_addr); | 203 | ipv6_dev_ac_dec(dev, &pac->acl_addr); |
202 | dev_put(dev); | 204 | dev_put(dev); |
@@ -210,6 +212,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
210 | struct ipv6_pinfo *np = inet6_sk(sk); | 212 | struct ipv6_pinfo *np = inet6_sk(sk); |
211 | struct net_device *dev = NULL; | 213 | struct net_device *dev = NULL; |
212 | struct ipv6_ac_socklist *pac; | 214 | struct ipv6_ac_socklist *pac; |
215 | struct net *net = sock_net(sk); | ||
213 | int prev_index; | 216 | int prev_index; |
214 | 217 | ||
215 | write_lock_bh(&ipv6_sk_ac_lock); | 218 | write_lock_bh(&ipv6_sk_ac_lock); |
@@ -224,7 +227,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
224 | if (pac->acl_ifindex != prev_index) { | 227 | if (pac->acl_ifindex != prev_index) { |
225 | if (dev) | 228 | if (dev) |
226 | dev_put(dev); | 229 | dev_put(dev); |
227 | dev = dev_get_by_index(&init_net, pac->acl_ifindex); | 230 | dev = dev_get_by_index(net, pac->acl_ifindex); |
228 | prev_index = pac->acl_ifindex; | 231 | prev_index = pac->acl_ifindex; |
229 | } | 232 | } |
230 | if (dev) | 233 | if (dev) |
@@ -422,14 +425,15 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) | |||
422 | /* | 425 | /* |
423 | * check if given interface (or any, if dev==0) has this anycast address | 426 | * check if given interface (or any, if dev==0) has this anycast address |
424 | */ | 427 | */ |
425 | int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr) | 428 | int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
429 | struct in6_addr *addr) | ||
426 | { | 430 | { |
427 | int found = 0; | 431 | int found = 0; |
428 | 432 | ||
429 | if (dev) | 433 | if (dev) |
430 | return ipv6_chk_acast_dev(dev, addr); | 434 | return ipv6_chk_acast_dev(dev, addr); |
431 | read_lock(&dev_base_lock); | 435 | read_lock(&dev_base_lock); |
432 | for_each_netdev(&init_net, dev) | 436 | for_each_netdev(net, dev) |
433 | if (ipv6_chk_acast_dev(dev, addr)) { | 437 | if (ipv6_chk_acast_dev(dev, addr)) { |
434 | found = 1; | 438 | found = 1; |
435 | break; | 439 | break; |
@@ -441,6 +445,7 @@ int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr) | |||
441 | 445 | ||
442 | #ifdef CONFIG_PROC_FS | 446 | #ifdef CONFIG_PROC_FS |
443 | struct ac6_iter_state { | 447 | struct ac6_iter_state { |
448 | struct seq_net_private p; | ||
444 | struct net_device *dev; | 449 | struct net_device *dev; |
445 | struct inet6_dev *idev; | 450 | struct inet6_dev *idev; |
446 | }; | 451 | }; |
@@ -451,9 +456,10 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) | |||
451 | { | 456 | { |
452 | struct ifacaddr6 *im = NULL; | 457 | struct ifacaddr6 *im = NULL; |
453 | struct ac6_iter_state *state = ac6_seq_private(seq); | 458 | struct ac6_iter_state *state = ac6_seq_private(seq); |
459 | struct net *net = seq_file_net(seq); | ||
454 | 460 | ||
455 | state->idev = NULL; | 461 | state->idev = NULL; |
456 | for_each_netdev(&init_net, state->dev) { | 462 | for_each_netdev(net, state->dev) { |
457 | struct inet6_dev *idev; | 463 | struct inet6_dev *idev; |
458 | idev = in6_dev_get(state->dev); | 464 | idev = in6_dev_get(state->dev); |
459 | if (!idev) | 465 | if (!idev) |
@@ -551,8 +557,8 @@ static const struct seq_operations ac6_seq_ops = { | |||
551 | 557 | ||
552 | static int ac6_seq_open(struct inode *inode, struct file *file) | 558 | static int ac6_seq_open(struct inode *inode, struct file *file) |
553 | { | 559 | { |
554 | return seq_open_private(file, &ac6_seq_ops, | 560 | return seq_open_net(inode, file, &ac6_seq_ops, |
555 | sizeof(struct ac6_iter_state)); | 561 | sizeof(struct ac6_iter_state)); |
556 | } | 562 | } |
557 | 563 | ||
558 | static const struct file_operations ac6_seq_fops = { | 564 | static const struct file_operations ac6_seq_fops = { |
@@ -560,20 +566,20 @@ static const struct file_operations ac6_seq_fops = { | |||
560 | .open = ac6_seq_open, | 566 | .open = ac6_seq_open, |
561 | .read = seq_read, | 567 | .read = seq_read, |
562 | .llseek = seq_lseek, | 568 | .llseek = seq_lseek, |
563 | .release = seq_release_private, | 569 | .release = seq_release_net, |
564 | }; | 570 | }; |
565 | 571 | ||
566 | int __init ac6_proc_init(void) | 572 | int ac6_proc_init(struct net *net) |
567 | { | 573 | { |
568 | if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops)) | 574 | if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops)) |
569 | return -ENOMEM; | 575 | return -ENOMEM; |
570 | 576 | ||
571 | return 0; | 577 | return 0; |
572 | } | 578 | } |
573 | 579 | ||
574 | void ac6_proc_exit(void) | 580 | void ac6_proc_exit(struct net *net) |
575 | { | 581 | { |
576 | proc_net_remove(&init_net, "anycast6"); | 582 | proc_net_remove(net, "anycast6"); |
577 | } | 583 | } |
578 | #endif | 584 | #endif |
579 | 585 | ||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 695c0ca8a417..cac580749ebe 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -29,24 +29,22 @@ struct fib6_rule | |||
29 | u8 tclass; | 29 | u8 tclass; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static struct fib_rules_ops fib6_rules_ops; | 32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
33 | 33 | int flags, pol_lookup_t lookup) | |
34 | struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, | ||
35 | pol_lookup_t lookup) | ||
36 | { | 34 | { |
37 | struct fib_lookup_arg arg = { | 35 | struct fib_lookup_arg arg = { |
38 | .lookup_ptr = lookup, | 36 | .lookup_ptr = lookup, |
39 | }; | 37 | }; |
40 | 38 | ||
41 | fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg); | 39 | fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg); |
42 | if (arg.rule) | 40 | if (arg.rule) |
43 | fib_rule_put(arg.rule); | 41 | fib_rule_put(arg.rule); |
44 | 42 | ||
45 | if (arg.result) | 43 | if (arg.result) |
46 | return arg.result; | 44 | return arg.result; |
47 | 45 | ||
48 | dst_hold(&ip6_null_entry.u.dst); | 46 | dst_hold(&net->ipv6.ip6_null_entry->u.dst); |
49 | return &ip6_null_entry.u.dst; | 47 | return &net->ipv6.ip6_null_entry->u.dst; |
50 | } | 48 | } |
51 | 49 | ||
52 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
@@ -54,28 +52,29 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
54 | { | 52 | { |
55 | struct rt6_info *rt = NULL; | 53 | struct rt6_info *rt = NULL; |
56 | struct fib6_table *table; | 54 | struct fib6_table *table; |
55 | struct net *net = rule->fr_net; | ||
57 | pol_lookup_t lookup = arg->lookup_ptr; | 56 | pol_lookup_t lookup = arg->lookup_ptr; |
58 | 57 | ||
59 | switch (rule->action) { | 58 | switch (rule->action) { |
60 | case FR_ACT_TO_TBL: | 59 | case FR_ACT_TO_TBL: |
61 | break; | 60 | break; |
62 | case FR_ACT_UNREACHABLE: | 61 | case FR_ACT_UNREACHABLE: |
63 | rt = &ip6_null_entry; | 62 | rt = net->ipv6.ip6_null_entry; |
64 | goto discard_pkt; | 63 | goto discard_pkt; |
65 | default: | 64 | default: |
66 | case FR_ACT_BLACKHOLE: | 65 | case FR_ACT_BLACKHOLE: |
67 | rt = &ip6_blk_hole_entry; | 66 | rt = net->ipv6.ip6_blk_hole_entry; |
68 | goto discard_pkt; | 67 | goto discard_pkt; |
69 | case FR_ACT_PROHIBIT: | 68 | case FR_ACT_PROHIBIT: |
70 | rt = &ip6_prohibit_entry; | 69 | rt = net->ipv6.ip6_prohibit_entry; |
71 | goto discard_pkt; | 70 | goto discard_pkt; |
72 | } | 71 | } |
73 | 72 | ||
74 | table = fib6_get_table(rule->table); | 73 | table = fib6_get_table(net, rule->table); |
75 | if (table) | 74 | if (table) |
76 | rt = lookup(table, flp, flags); | 75 | rt = lookup(net, table, flp, flags); |
77 | 76 | ||
78 | if (rt != &ip6_null_entry) { | 77 | if (rt != net->ipv6.ip6_null_entry) { |
79 | struct fib6_rule *r = (struct fib6_rule *)rule; | 78 | struct fib6_rule *r = (struct fib6_rule *)rule; |
80 | 79 | ||
81 | /* | 80 | /* |
@@ -85,8 +84,18 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
85 | if ((rule->flags & FIB_RULE_FIND_SADDR) && | 84 | if ((rule->flags & FIB_RULE_FIND_SADDR) && |
86 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { | 85 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { |
87 | struct in6_addr saddr; | 86 | struct in6_addr saddr; |
88 | if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst, | 87 | unsigned int srcprefs = 0; |
89 | &saddr)) | 88 | |
89 | if (flags & RT6_LOOKUP_F_SRCPREF_TMP) | ||
90 | srcprefs |= IPV6_PREFER_SRC_TMP; | ||
91 | if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC) | ||
92 | srcprefs |= IPV6_PREFER_SRC_PUBLIC; | ||
93 | if (flags & RT6_LOOKUP_F_SRCPREF_COA) | ||
94 | srcprefs |= IPV6_PREFER_SRC_COA; | ||
95 | |||
96 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, | ||
97 | &flp->fl6_dst, srcprefs, | ||
98 | &saddr)) | ||
90 | goto again; | 99 | goto again; |
91 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 100 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
92 | r->src.plen)) | 101 | r->src.plen)) |
@@ -145,13 +154,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
145 | struct nlattr **tb) | 154 | struct nlattr **tb) |
146 | { | 155 | { |
147 | int err = -EINVAL; | 156 | int err = -EINVAL; |
157 | struct net *net = sock_net(skb->sk); | ||
148 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 158 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
149 | 159 | ||
150 | if (rule->action == FR_ACT_TO_TBL) { | 160 | if (rule->action == FR_ACT_TO_TBL) { |
151 | if (rule->table == RT6_TABLE_UNSPEC) | 161 | if (rule->table == RT6_TABLE_UNSPEC) |
152 | goto errout; | 162 | goto errout; |
153 | 163 | ||
154 | if (fib6_new_table(rule->table) == NULL) { | 164 | if (fib6_new_table(net, rule->table) == NULL) { |
155 | err = -ENOBUFS; | 165 | err = -ENOBUFS; |
156 | goto errout; | 166 | goto errout; |
157 | } | 167 | } |
@@ -234,7 +244,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
234 | + nla_total_size(16); /* src */ | 244 | + nla_total_size(16); /* src */ |
235 | } | 245 | } |
236 | 246 | ||
237 | static struct fib_rules_ops fib6_rules_ops = { | 247 | static struct fib_rules_ops fib6_rules_ops_template = { |
238 | .family = AF_INET6, | 248 | .family = AF_INET6, |
239 | .rule_size = sizeof(struct fib6_rule), | 249 | .rule_size = sizeof(struct fib6_rule), |
240 | .addr_size = sizeof(struct in6_addr), | 250 | .addr_size = sizeof(struct in6_addr), |
@@ -247,45 +257,64 @@ static struct fib_rules_ops fib6_rules_ops = { | |||
247 | .nlmsg_payload = fib6_rule_nlmsg_payload, | 257 | .nlmsg_payload = fib6_rule_nlmsg_payload, |
248 | .nlgroup = RTNLGRP_IPV6_RULE, | 258 | .nlgroup = RTNLGRP_IPV6_RULE, |
249 | .policy = fib6_rule_policy, | 259 | .policy = fib6_rule_policy, |
250 | .rules_list = LIST_HEAD_INIT(fib6_rules_ops.rules_list), | ||
251 | .owner = THIS_MODULE, | 260 | .owner = THIS_MODULE, |
252 | .fro_net = &init_net, | 261 | .fro_net = &init_net, |
253 | }; | 262 | }; |
254 | 263 | ||
255 | static int __init fib6_default_rules_init(void) | 264 | static int fib6_rules_net_init(struct net *net) |
256 | { | 265 | { |
257 | int err; | 266 | int err = -ENOMEM; |
258 | 267 | ||
259 | err = fib_default_rule_add(&fib6_rules_ops, 0, | 268 | net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template, |
260 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); | 269 | sizeof(*net->ipv6.fib6_rules_ops), |
261 | if (err < 0) | 270 | GFP_KERNEL); |
262 | return err; | 271 | if (!net->ipv6.fib6_rules_ops) |
263 | err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0); | 272 | goto out; |
264 | if (err < 0) | ||
265 | return err; | ||
266 | return 0; | ||
267 | } | ||
268 | 273 | ||
269 | int __init fib6_rules_init(void) | 274 | net->ipv6.fib6_rules_ops->fro_net = net; |
270 | { | 275 | INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list); |
271 | int ret; | ||
272 | 276 | ||
273 | ret = fib6_default_rules_init(); | 277 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0, |
274 | if (ret) | 278 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); |
275 | goto out; | 279 | if (err) |
280 | goto out_fib6_rules_ops; | ||
276 | 281 | ||
277 | ret = fib_rules_register(&fib6_rules_ops); | 282 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, |
278 | if (ret) | 283 | 0x7FFE, RT6_TABLE_MAIN, 0); |
279 | goto out_default_rules_init; | 284 | if (err) |
285 | goto out_fib6_default_rule_add; | ||
286 | |||
287 | err = fib_rules_register(net->ipv6.fib6_rules_ops); | ||
288 | if (err) | ||
289 | goto out_fib6_default_rule_add; | ||
280 | out: | 290 | out: |
281 | return ret; | 291 | return err; |
282 | 292 | ||
283 | out_default_rules_init: | 293 | out_fib6_default_rule_add: |
284 | fib_rules_cleanup_ops(&fib6_rules_ops); | 294 | fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops); |
295 | out_fib6_rules_ops: | ||
296 | kfree(net->ipv6.fib6_rules_ops); | ||
285 | goto out; | 297 | goto out; |
286 | } | 298 | } |
287 | 299 | ||
300 | static void fib6_rules_net_exit(struct net *net) | ||
301 | { | ||
302 | fib_rules_unregister(net->ipv6.fib6_rules_ops); | ||
303 | kfree(net->ipv6.fib6_rules_ops); | ||
304 | } | ||
305 | |||
306 | static struct pernet_operations fib6_rules_net_ops = { | ||
307 | .init = fib6_rules_net_init, | ||
308 | .exit = fib6_rules_net_exit, | ||
309 | }; | ||
310 | |||
311 | int __init fib6_rules_init(void) | ||
312 | { | ||
313 | return register_pernet_subsys(&fib6_rules_net_ops); | ||
314 | } | ||
315 | |||
316 | |||
288 | void fib6_rules_cleanup(void) | 317 | void fib6_rules_cleanup(void) |
289 | { | 318 | { |
290 | fib_rules_unregister(&fib6_rules_ops); | 319 | return unregister_pernet_subsys(&fib6_rules_net_ops); |
291 | } | 320 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 121d517bf91c..63309d10df3a 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -80,8 +80,10 @@ EXPORT_SYMBOL(icmpv6msg_statistics); | |||
80 | * | 80 | * |
81 | * On SMP we have one ICMP socket per-cpu. | 81 | * On SMP we have one ICMP socket per-cpu. |
82 | */ | 82 | */ |
83 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; | 83 | static inline struct sock *icmpv6_sk(struct net *net) |
84 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) | 84 | { |
85 | return net->ipv6.icmp_sk[smp_processor_id()]; | ||
86 | } | ||
85 | 87 | ||
86 | static int icmpv6_rcv(struct sk_buff *skb); | 88 | static int icmpv6_rcv(struct sk_buff *skb); |
87 | 89 | ||
@@ -90,11 +92,11 @@ static struct inet6_protocol icmpv6_protocol = { | |||
90 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 92 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
91 | }; | 93 | }; |
92 | 94 | ||
93 | static __inline__ int icmpv6_xmit_lock(void) | 95 | static __inline__ int icmpv6_xmit_lock(struct sock *sk) |
94 | { | 96 | { |
95 | local_bh_disable(); | 97 | local_bh_disable(); |
96 | 98 | ||
97 | if (unlikely(!spin_trylock(&icmpv6_socket->sk->sk_lock.slock))) { | 99 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
98 | /* This can happen if the output path (f.e. SIT or | 100 | /* This can happen if the output path (f.e. SIT or |
99 | * ip6ip6 tunnel) signals dst_link_failure() for an | 101 | * ip6ip6 tunnel) signals dst_link_failure() for an |
100 | * outgoing ICMP6 packet. | 102 | * outgoing ICMP6 packet. |
@@ -105,9 +107,9 @@ static __inline__ int icmpv6_xmit_lock(void) | |||
105 | return 0; | 107 | return 0; |
106 | } | 108 | } |
107 | 109 | ||
108 | static __inline__ void icmpv6_xmit_unlock(void) | 110 | static __inline__ void icmpv6_xmit_unlock(struct sock *sk) |
109 | { | 111 | { |
110 | spin_unlock_bh(&icmpv6_socket->sk->sk_lock.slock); | 112 | spin_unlock_bh(&sk->sk_lock.slock); |
111 | } | 113 | } |
112 | 114 | ||
113 | /* | 115 | /* |
@@ -161,6 +163,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
161 | struct flowi *fl) | 163 | struct flowi *fl) |
162 | { | 164 | { |
163 | struct dst_entry *dst; | 165 | struct dst_entry *dst; |
166 | struct net *net = sock_net(sk); | ||
164 | int res = 0; | 167 | int res = 0; |
165 | 168 | ||
166 | /* Informational messages are not limited. */ | 169 | /* Informational messages are not limited. */ |
@@ -176,7 +179,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
176 | * XXX: perhaps the expire for routing entries cloned by | 179 | * XXX: perhaps the expire for routing entries cloned by |
177 | * this lookup should be more aggressive (not longer than timeout). | 180 | * this lookup should be more aggressive (not longer than timeout). |
178 | */ | 181 | */ |
179 | dst = ip6_route_output(sk, fl); | 182 | dst = ip6_route_output(net, sk, fl); |
180 | if (dst->error) { | 183 | if (dst->error) { |
181 | IP6_INC_STATS(ip6_dst_idev(dst), | 184 | IP6_INC_STATS(ip6_dst_idev(dst), |
182 | IPSTATS_MIB_OUTNOROUTES); | 185 | IPSTATS_MIB_OUTNOROUTES); |
@@ -184,7 +187,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
184 | res = 1; | 187 | res = 1; |
185 | } else { | 188 | } else { |
186 | struct rt6_info *rt = (struct rt6_info *)dst; | 189 | struct rt6_info *rt = (struct rt6_info *)dst; |
187 | int tmo = init_net.ipv6.sysctl.icmpv6_time; | 190 | int tmo = net->ipv6.sysctl.icmpv6_time; |
188 | 191 | ||
189 | /* Give more bandwidth to wider prefixes. */ | 192 | /* Give more bandwidth to wider prefixes. */ |
190 | if (rt->rt6i_dst.plen < 128) | 193 | if (rt->rt6i_dst.plen < 128) |
@@ -303,6 +306,7 @@ static inline void mip6_addr_swap(struct sk_buff *skb) {} | |||
303 | void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | 306 | void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, |
304 | struct net_device *dev) | 307 | struct net_device *dev) |
305 | { | 308 | { |
309 | struct net *net = dev_net(skb->dev); | ||
306 | struct inet6_dev *idev = NULL; | 310 | struct inet6_dev *idev = NULL; |
307 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 311 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
308 | struct sock *sk; | 312 | struct sock *sk; |
@@ -332,7 +336,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
332 | */ | 336 | */ |
333 | addr_type = ipv6_addr_type(&hdr->daddr); | 337 | addr_type = ipv6_addr_type(&hdr->daddr); |
334 | 338 | ||
335 | if (ipv6_chk_addr(&init_net, &hdr->daddr, skb->dev, 0)) | 339 | if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0)) |
336 | saddr = &hdr->daddr; | 340 | saddr = &hdr->daddr; |
337 | 341 | ||
338 | /* | 342 | /* |
@@ -389,12 +393,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
389 | fl.fl_icmp_code = code; | 393 | fl.fl_icmp_code = code; |
390 | security_skb_classify_flow(skb, &fl); | 394 | security_skb_classify_flow(skb, &fl); |
391 | 395 | ||
392 | if (icmpv6_xmit_lock()) | 396 | sk = icmpv6_sk(net); |
393 | return; | ||
394 | |||
395 | sk = icmpv6_socket->sk; | ||
396 | np = inet6_sk(sk); | 397 | np = inet6_sk(sk); |
397 | 398 | ||
399 | if (icmpv6_xmit_lock(sk)) | ||
400 | return; | ||
401 | |||
398 | if (!icmpv6_xrlim_allow(sk, type, &fl)) | 402 | if (!icmpv6_xrlim_allow(sk, type, &fl)) |
399 | goto out; | 403 | goto out; |
400 | 404 | ||
@@ -460,9 +464,7 @@ route_done: | |||
460 | else | 464 | else |
461 | hlimit = np->hop_limit; | 465 | hlimit = np->hop_limit; |
462 | if (hlimit < 0) | 466 | if (hlimit < 0) |
463 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 467 | hlimit = ip6_dst_hoplimit(dst); |
464 | if (hlimit < 0) | ||
465 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
466 | 468 | ||
467 | tclass = np->tclass; | 469 | tclass = np->tclass; |
468 | if (tclass < 0) | 470 | if (tclass < 0) |
@@ -498,13 +500,14 @@ out_put: | |||
498 | out_dst_release: | 500 | out_dst_release: |
499 | dst_release(dst); | 501 | dst_release(dst); |
500 | out: | 502 | out: |
501 | icmpv6_xmit_unlock(); | 503 | icmpv6_xmit_unlock(sk); |
502 | } | 504 | } |
503 | 505 | ||
504 | EXPORT_SYMBOL(icmpv6_send); | 506 | EXPORT_SYMBOL(icmpv6_send); |
505 | 507 | ||
506 | static void icmpv6_echo_reply(struct sk_buff *skb) | 508 | static void icmpv6_echo_reply(struct sk_buff *skb) |
507 | { | 509 | { |
510 | struct net *net = dev_net(skb->dev); | ||
508 | struct sock *sk; | 511 | struct sock *sk; |
509 | struct inet6_dev *idev; | 512 | struct inet6_dev *idev; |
510 | struct ipv6_pinfo *np; | 513 | struct ipv6_pinfo *np; |
@@ -535,12 +538,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
535 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 538 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; |
536 | security_skb_classify_flow(skb, &fl); | 539 | security_skb_classify_flow(skb, &fl); |
537 | 540 | ||
538 | if (icmpv6_xmit_lock()) | 541 | sk = icmpv6_sk(net); |
539 | return; | ||
540 | |||
541 | sk = icmpv6_socket->sk; | ||
542 | np = inet6_sk(sk); | 542 | np = inet6_sk(sk); |
543 | 543 | ||
544 | if (icmpv6_xmit_lock(sk)) | ||
545 | return; | ||
546 | |||
544 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 547 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
545 | fl.oif = np->mcast_oif; | 548 | fl.oif = np->mcast_oif; |
546 | 549 | ||
@@ -555,9 +558,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
555 | else | 558 | else |
556 | hlimit = np->hop_limit; | 559 | hlimit = np->hop_limit; |
557 | if (hlimit < 0) | 560 | if (hlimit < 0) |
558 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 561 | hlimit = ip6_dst_hoplimit(dst); |
559 | if (hlimit < 0) | ||
560 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
561 | 562 | ||
562 | tclass = np->tclass; | 563 | tclass = np->tclass; |
563 | if (tclass < 0) | 564 | if (tclass < 0) |
@@ -584,7 +585,7 @@ out_put: | |||
584 | in6_dev_put(idev); | 585 | in6_dev_put(idev); |
585 | dst_release(dst); | 586 | dst_release(dst); |
586 | out: | 587 | out: |
587 | icmpv6_xmit_unlock(); | 588 | icmpv6_xmit_unlock(sk); |
588 | } | 589 | } |
589 | 590 | ||
590 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | 591 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) |
@@ -775,19 +776,41 @@ drop_no_count: | |||
775 | return 0; | 776 | return 0; |
776 | } | 777 | } |
777 | 778 | ||
779 | void icmpv6_flow_init(struct sock *sk, struct flowi *fl, | ||
780 | u8 type, | ||
781 | const struct in6_addr *saddr, | ||
782 | const struct in6_addr *daddr, | ||
783 | int oif) | ||
784 | { | ||
785 | memset(fl, 0, sizeof(*fl)); | ||
786 | ipv6_addr_copy(&fl->fl6_src, saddr); | ||
787 | ipv6_addr_copy(&fl->fl6_dst, daddr); | ||
788 | fl->proto = IPPROTO_ICMPV6; | ||
789 | fl->fl_icmp_type = type; | ||
790 | fl->fl_icmp_code = 0; | ||
791 | fl->oif = oif; | ||
792 | security_sk_classify_flow(sk, fl); | ||
793 | } | ||
794 | |||
778 | /* | 795 | /* |
779 | * Special lock-class for __icmpv6_socket: | 796 | * Special lock-class for __icmpv6_sk: |
780 | */ | 797 | */ |
781 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; | 798 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; |
782 | 799 | ||
783 | int __init icmpv6_init(struct net_proto_family *ops) | 800 | static int __net_init icmpv6_sk_init(struct net *net) |
784 | { | 801 | { |
785 | struct sock *sk; | 802 | struct sock *sk; |
786 | int err, i, j; | 803 | int err, i, j; |
787 | 804 | ||
805 | net->ipv6.icmp_sk = | ||
806 | kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); | ||
807 | if (net->ipv6.icmp_sk == NULL) | ||
808 | return -ENOMEM; | ||
809 | |||
788 | for_each_possible_cpu(i) { | 810 | for_each_possible_cpu(i) { |
811 | struct socket *sock; | ||
789 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, | 812 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, |
790 | &per_cpu(__icmpv6_socket, i)); | 813 | &sock); |
791 | if (err < 0) { | 814 | if (err < 0) { |
792 | printk(KERN_ERR | 815 | printk(KERN_ERR |
793 | "Failed to initialize the ICMP6 control socket " | 816 | "Failed to initialize the ICMP6 control socket " |
@@ -796,12 +819,14 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
796 | goto fail; | 819 | goto fail; |
797 | } | 820 | } |
798 | 821 | ||
799 | sk = per_cpu(__icmpv6_socket, i)->sk; | 822 | net->ipv6.icmp_sk[i] = sk = sock->sk; |
823 | sk_change_net(sk, net); | ||
824 | |||
800 | sk->sk_allocation = GFP_ATOMIC; | 825 | sk->sk_allocation = GFP_ATOMIC; |
801 | /* | 826 | /* |
802 | * Split off their lock-class, because sk->sk_dst_lock | 827 | * Split off their lock-class, because sk->sk_dst_lock |
803 | * gets used from softirqs, which is safe for | 828 | * gets used from softirqs, which is safe for |
804 | * __icmpv6_socket (because those never get directly used | 829 | * __icmpv6_sk (because those never get directly used |
805 | * via userspace syscalls), but unsafe for normal sockets. | 830 | * via userspace syscalls), but unsafe for normal sockets. |
806 | */ | 831 | */ |
807 | lockdep_set_class(&sk->sk_dst_lock, | 832 | lockdep_set_class(&sk->sk_dst_lock, |
@@ -815,36 +840,56 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
815 | 840 | ||
816 | sk->sk_prot->unhash(sk); | 841 | sk->sk_prot->unhash(sk); |
817 | } | 842 | } |
818 | |||
819 | |||
820 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) { | ||
821 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
822 | err = -EAGAIN; | ||
823 | goto fail; | ||
824 | } | ||
825 | |||
826 | return 0; | 843 | return 0; |
827 | 844 | ||
828 | fail: | 845 | fail: |
829 | for (j = 0; j < i; j++) { | 846 | for (j = 0; j < i; j++) |
830 | if (!cpu_possible(j)) | 847 | sk_release_kernel(net->ipv6.icmp_sk[j]); |
831 | continue; | 848 | kfree(net->ipv6.icmp_sk); |
832 | sock_release(per_cpu(__icmpv6_socket, j)); | ||
833 | } | ||
834 | |||
835 | return err; | 849 | return err; |
836 | } | 850 | } |
837 | 851 | ||
838 | void icmpv6_cleanup(void) | 852 | static void __net_exit icmpv6_sk_exit(struct net *net) |
839 | { | 853 | { |
840 | int i; | 854 | int i; |
841 | 855 | ||
842 | for_each_possible_cpu(i) { | 856 | for_each_possible_cpu(i) { |
843 | sock_release(per_cpu(__icmpv6_socket, i)); | 857 | sk_release_kernel(net->ipv6.icmp_sk[i]); |
844 | } | 858 | } |
859 | kfree(net->ipv6.icmp_sk); | ||
860 | } | ||
861 | |||
862 | static struct pernet_operations icmpv6_sk_ops = { | ||
863 | .init = icmpv6_sk_init, | ||
864 | .exit = icmpv6_sk_exit, | ||
865 | }; | ||
866 | |||
867 | int __init icmpv6_init(void) | ||
868 | { | ||
869 | int err; | ||
870 | |||
871 | err = register_pernet_subsys(&icmpv6_sk_ops); | ||
872 | if (err < 0) | ||
873 | return err; | ||
874 | |||
875 | err = -EAGAIN; | ||
876 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) | ||
877 | goto fail; | ||
878 | return 0; | ||
879 | |||
880 | fail: | ||
881 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
882 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
883 | return err; | ||
884 | } | ||
885 | |||
886 | void icmpv6_cleanup(void) | ||
887 | { | ||
888 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
845 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | 889 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); |
846 | } | 890 | } |
847 | 891 | ||
892 | |||
848 | static const struct icmp6_err { | 893 | static const struct icmp6_err { |
849 | int err; | 894 | int err; |
850 | int fatal; | 895 | int fatal; |
@@ -925,6 +970,10 @@ struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) | |||
925 | table = kmemdup(ipv6_icmp_table_template, | 970 | table = kmemdup(ipv6_icmp_table_template, |
926 | sizeof(ipv6_icmp_table_template), | 971 | sizeof(ipv6_icmp_table_template), |
927 | GFP_KERNEL); | 972 | GFP_KERNEL); |
973 | |||
974 | if (table) | ||
975 | table[0].data = &net->ipv6.sysctl.icmpv6_time; | ||
976 | |||
928 | return table; | 977 | return table; |
929 | } | 978 | } |
930 | #endif | 979 | #endif |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 99fd25f7f005..340c7d42b83a 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | void __inet6_hash(struct sock *sk) | 25 | void __inet6_hash(struct sock *sk) |
26 | { | 26 | { |
27 | struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; | 27 | struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; |
28 | struct hlist_head *list; | 28 | struct hlist_head *list; |
29 | rwlock_t *lock; | 29 | rwlock_t *lock; |
30 | 30 | ||
@@ -105,7 +105,7 @@ struct sock *inet6_lookup_listener(struct net *net, | |||
105 | 105 | ||
106 | read_lock(&hashinfo->lhash_lock); | 106 | read_lock(&hashinfo->lhash_lock); |
107 | sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { | 107 | sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { |
108 | if (sk->sk_net == net && inet_sk(sk)->num == hnum && | 108 | if (net_eq(sock_net(sk), net) && inet_sk(sk)->num == hnum && |
109 | sk->sk_family == PF_INET6) { | 109 | sk->sk_family == PF_INET6) { |
110 | const struct ipv6_pinfo *np = inet6_sk(sk); | 110 | const struct ipv6_pinfo *np = inet6_sk(sk); |
111 | 111 | ||
@@ -172,7 +172,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, | |||
172 | struct sock *sk2; | 172 | struct sock *sk2; |
173 | const struct hlist_node *node; | 173 | const struct hlist_node *node; |
174 | struct inet_timewait_sock *tw; | 174 | struct inet_timewait_sock *tw; |
175 | struct net *net = sk->sk_net; | 175 | struct net *net = sock_net(sk); |
176 | 176 | ||
177 | prefetch(head->chain.first); | 177 | prefetch(head->chain.first); |
178 | write_lock(lock); | 178 | write_lock(lock); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index bab72b6f1444..b3f6e03c454c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -48,8 +48,6 @@ | |||
48 | #define RT6_TRACE(x...) do { ; } while (0) | 48 | #define RT6_TRACE(x...) do { ; } while (0) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | struct rt6_statistics rt6_stats; | ||
52 | |||
53 | static struct kmem_cache * fib6_node_kmem __read_mostly; | 51 | static struct kmem_cache * fib6_node_kmem __read_mostly; |
54 | 52 | ||
55 | enum fib_walk_state_t | 53 | enum fib_walk_state_t |
@@ -66,6 +64,7 @@ enum fib_walk_state_t | |||
66 | struct fib6_cleaner_t | 64 | struct fib6_cleaner_t |
67 | { | 65 | { |
68 | struct fib6_walker_t w; | 66 | struct fib6_walker_t w; |
67 | struct net *net; | ||
69 | int (*func)(struct rt6_info *, void *arg); | 68 | int (*func)(struct rt6_info *, void *arg); |
70 | void *arg; | 69 | void *arg; |
71 | }; | 70 | }; |
@@ -78,9 +77,10 @@ static DEFINE_RWLOCK(fib6_walker_lock); | |||
78 | #define FWS_INIT FWS_L | 77 | #define FWS_INIT FWS_L |
79 | #endif | 78 | #endif |
80 | 79 | ||
81 | static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt); | 80 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, |
82 | static struct rt6_info * fib6_find_prefix(struct fib6_node *fn); | 81 | struct rt6_info *rt); |
83 | static struct fib6_node * fib6_repair_tree(struct fib6_node *fn); | 82 | static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn); |
83 | static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn); | ||
84 | static int fib6_walk(struct fib6_walker_t *w); | 84 | static int fib6_walk(struct fib6_walker_t *w); |
85 | static int fib6_walk_continue(struct fib6_walker_t *w); | 85 | static int fib6_walk_continue(struct fib6_walker_t *w); |
86 | 86 | ||
@@ -93,7 +93,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w); | |||
93 | 93 | ||
94 | static __u32 rt_sernum; | 94 | static __u32 rt_sernum; |
95 | 95 | ||
96 | static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0); | 96 | static void fib6_gc_timer_cb(unsigned long arg); |
97 | 97 | ||
98 | static struct fib6_walker_t fib6_walker_list = { | 98 | static struct fib6_walker_t fib6_walker_list = { |
99 | .prev = &fib6_walker_list, | 99 | .prev = &fib6_walker_list, |
@@ -166,22 +166,13 @@ static __inline__ void rt6_release(struct rt6_info *rt) | |||
166 | dst_free(&rt->u.dst); | 166 | dst_free(&rt->u.dst); |
167 | } | 167 | } |
168 | 168 | ||
169 | static struct fib6_table fib6_main_tbl = { | ||
170 | .tb6_id = RT6_TABLE_MAIN, | ||
171 | .tb6_root = { | ||
172 | .leaf = &ip6_null_entry, | ||
173 | .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 169 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
178 | #define FIB_TABLE_HASHSZ 256 | 170 | #define FIB_TABLE_HASHSZ 256 |
179 | #else | 171 | #else |
180 | #define FIB_TABLE_HASHSZ 1 | 172 | #define FIB_TABLE_HASHSZ 1 |
181 | #endif | 173 | #endif |
182 | static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; | ||
183 | 174 | ||
184 | static void fib6_link_table(struct fib6_table *tb) | 175 | static void fib6_link_table(struct net *net, struct fib6_table *tb) |
185 | { | 176 | { |
186 | unsigned int h; | 177 | unsigned int h; |
187 | 178 | ||
@@ -197,52 +188,46 @@ static void fib6_link_table(struct fib6_table *tb) | |||
197 | * No protection necessary, this is the only list mutatation | 188 | * No protection necessary, this is the only list mutatation |
198 | * operation, tables never disappear once they exist. | 189 | * operation, tables never disappear once they exist. |
199 | */ | 190 | */ |
200 | hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]); | 191 | hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]); |
201 | } | 192 | } |
202 | 193 | ||
203 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 194 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
204 | static struct fib6_table fib6_local_tbl = { | ||
205 | .tb6_id = RT6_TABLE_LOCAL, | ||
206 | .tb6_root = { | ||
207 | .leaf = &ip6_null_entry, | ||
208 | .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, | ||
209 | }, | ||
210 | }; | ||
211 | 195 | ||
212 | static struct fib6_table *fib6_alloc_table(u32 id) | 196 | static struct fib6_table *fib6_alloc_table(struct net *net, u32 id) |
213 | { | 197 | { |
214 | struct fib6_table *table; | 198 | struct fib6_table *table; |
215 | 199 | ||
216 | table = kzalloc(sizeof(*table), GFP_ATOMIC); | 200 | table = kzalloc(sizeof(*table), GFP_ATOMIC); |
217 | if (table != NULL) { | 201 | if (table != NULL) { |
218 | table->tb6_id = id; | 202 | table->tb6_id = id; |
219 | table->tb6_root.leaf = &ip6_null_entry; | 203 | table->tb6_root.leaf = net->ipv6.ip6_null_entry; |
220 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | 204 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
221 | } | 205 | } |
222 | 206 | ||
223 | return table; | 207 | return table; |
224 | } | 208 | } |
225 | 209 | ||
226 | struct fib6_table *fib6_new_table(u32 id) | 210 | struct fib6_table *fib6_new_table(struct net *net, u32 id) |
227 | { | 211 | { |
228 | struct fib6_table *tb; | 212 | struct fib6_table *tb; |
229 | 213 | ||
230 | if (id == 0) | 214 | if (id == 0) |
231 | id = RT6_TABLE_MAIN; | 215 | id = RT6_TABLE_MAIN; |
232 | tb = fib6_get_table(id); | 216 | tb = fib6_get_table(net, id); |
233 | if (tb) | 217 | if (tb) |
234 | return tb; | 218 | return tb; |
235 | 219 | ||
236 | tb = fib6_alloc_table(id); | 220 | tb = fib6_alloc_table(net, id); |
237 | if (tb != NULL) | 221 | if (tb != NULL) |
238 | fib6_link_table(tb); | 222 | fib6_link_table(net, tb); |
239 | 223 | ||
240 | return tb; | 224 | return tb; |
241 | } | 225 | } |
242 | 226 | ||
243 | struct fib6_table *fib6_get_table(u32 id) | 227 | struct fib6_table *fib6_get_table(struct net *net, u32 id) |
244 | { | 228 | { |
245 | struct fib6_table *tb; | 229 | struct fib6_table *tb; |
230 | struct hlist_head *head; | ||
246 | struct hlist_node *node; | 231 | struct hlist_node *node; |
247 | unsigned int h; | 232 | unsigned int h; |
248 | 233 | ||
@@ -250,7 +235,8 @@ struct fib6_table *fib6_get_table(u32 id) | |||
250 | id = RT6_TABLE_MAIN; | 235 | id = RT6_TABLE_MAIN; |
251 | h = id & (FIB_TABLE_HASHSZ - 1); | 236 | h = id & (FIB_TABLE_HASHSZ - 1); |
252 | rcu_read_lock(); | 237 | rcu_read_lock(); |
253 | hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) { | 238 | head = &net->ipv6.fib_table_hash[h]; |
239 | hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) { | ||
254 | if (tb->tb6_id == id) { | 240 | if (tb->tb6_id == id) { |
255 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
256 | return tb; | 242 | return tb; |
@@ -261,33 +247,32 @@ struct fib6_table *fib6_get_table(u32 id) | |||
261 | return NULL; | 247 | return NULL; |
262 | } | 248 | } |
263 | 249 | ||
264 | static void __init fib6_tables_init(void) | 250 | static void fib6_tables_init(struct net *net) |
265 | { | 251 | { |
266 | fib6_link_table(&fib6_main_tbl); | 252 | fib6_link_table(net, net->ipv6.fib6_main_tbl); |
267 | fib6_link_table(&fib6_local_tbl); | 253 | fib6_link_table(net, net->ipv6.fib6_local_tbl); |
268 | } | 254 | } |
269 | |||
270 | #else | 255 | #else |
271 | 256 | ||
272 | struct fib6_table *fib6_new_table(u32 id) | 257 | struct fib6_table *fib6_new_table(struct net *net, u32 id) |
273 | { | 258 | { |
274 | return fib6_get_table(id); | 259 | return fib6_get_table(net, id); |
275 | } | 260 | } |
276 | 261 | ||
277 | struct fib6_table *fib6_get_table(u32 id) | 262 | struct fib6_table *fib6_get_table(struct net *net, u32 id) |
278 | { | 263 | { |
279 | return &fib6_main_tbl; | 264 | return net->ipv6.fib6_main_tbl; |
280 | } | 265 | } |
281 | 266 | ||
282 | struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, | 267 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
283 | pol_lookup_t lookup) | 268 | int flags, pol_lookup_t lookup) |
284 | { | 269 | { |
285 | return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags); | 270 | return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags); |
286 | } | 271 | } |
287 | 272 | ||
288 | static void __init fib6_tables_init(void) | 273 | static void fib6_tables_init(struct net *net) |
289 | { | 274 | { |
290 | fib6_link_table(&fib6_main_tbl); | 275 | fib6_link_table(net, net->ipv6.fib6_main_tbl); |
291 | } | 276 | } |
292 | 277 | ||
293 | #endif | 278 | #endif |
@@ -361,18 +346,16 @@ end: | |||
361 | 346 | ||
362 | static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | 347 | static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) |
363 | { | 348 | { |
364 | struct net *net = skb->sk->sk_net; | 349 | struct net *net = sock_net(skb->sk); |
365 | unsigned int h, s_h; | 350 | unsigned int h, s_h; |
366 | unsigned int e = 0, s_e; | 351 | unsigned int e = 0, s_e; |
367 | struct rt6_rtnl_dump_arg arg; | 352 | struct rt6_rtnl_dump_arg arg; |
368 | struct fib6_walker_t *w; | 353 | struct fib6_walker_t *w; |
369 | struct fib6_table *tb; | 354 | struct fib6_table *tb; |
370 | struct hlist_node *node; | 355 | struct hlist_node *node; |
356 | struct hlist_head *head; | ||
371 | int res = 0; | 357 | int res = 0; |
372 | 358 | ||
373 | if (net != &init_net) | ||
374 | return 0; | ||
375 | |||
376 | s_h = cb->args[0]; | 359 | s_h = cb->args[0]; |
377 | s_e = cb->args[1]; | 360 | s_e = cb->args[1]; |
378 | 361 | ||
@@ -401,7 +384,8 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
401 | 384 | ||
402 | for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { | 385 | for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { |
403 | e = 0; | 386 | e = 0; |
404 | hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) { | 387 | head = &net->ipv6.fib_table_hash[h]; |
388 | hlist_for_each_entry(tb, node, head, tb6_hlist) { | ||
405 | if (e < s_e) | 389 | if (e < s_e) |
406 | goto next; | 390 | goto next; |
407 | res = fib6_dump_table(tb, skb, cb); | 391 | res = fib6_dump_table(tb, skb, cb); |
@@ -667,29 +651,29 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
667 | rt->rt6i_node = fn; | 651 | rt->rt6i_node = fn; |
668 | atomic_inc(&rt->rt6i_ref); | 652 | atomic_inc(&rt->rt6i_ref); |
669 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | 653 | inet6_rt_notify(RTM_NEWROUTE, rt, info); |
670 | rt6_stats.fib_rt_entries++; | 654 | info->nl_net->ipv6.rt6_stats->fib_rt_entries++; |
671 | 655 | ||
672 | if ((fn->fn_flags & RTN_RTINFO) == 0) { | 656 | if ((fn->fn_flags & RTN_RTINFO) == 0) { |
673 | rt6_stats.fib_route_nodes++; | 657 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
674 | fn->fn_flags |= RTN_RTINFO; | 658 | fn->fn_flags |= RTN_RTINFO; |
675 | } | 659 | } |
676 | 660 | ||
677 | return 0; | 661 | return 0; |
678 | } | 662 | } |
679 | 663 | ||
680 | static __inline__ void fib6_start_gc(struct rt6_info *rt) | 664 | static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt) |
681 | { | 665 | { |
682 | if (ip6_fib_timer.expires == 0 && | 666 | if (net->ipv6.ip6_fib_timer->expires == 0 && |
683 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) | 667 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) |
684 | mod_timer(&ip6_fib_timer, jiffies + | 668 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
685 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 669 | net->ipv6.sysctl.ip6_rt_gc_interval); |
686 | } | 670 | } |
687 | 671 | ||
688 | void fib6_force_start_gc(void) | 672 | void fib6_force_start_gc(struct net *net) |
689 | { | 673 | { |
690 | if (ip6_fib_timer.expires == 0) | 674 | if (net->ipv6.ip6_fib_timer->expires == 0) |
691 | mod_timer(&ip6_fib_timer, jiffies + | 675 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
692 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 676 | net->ipv6.sysctl.ip6_rt_gc_interval); |
693 | } | 677 | } |
694 | 678 | ||
695 | /* | 679 | /* |
@@ -733,8 +717,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
733 | if (sfn == NULL) | 717 | if (sfn == NULL) |
734 | goto st_failure; | 718 | goto st_failure; |
735 | 719 | ||
736 | sfn->leaf = &ip6_null_entry; | 720 | sfn->leaf = info->nl_net->ipv6.ip6_null_entry; |
737 | atomic_inc(&ip6_null_entry.rt6i_ref); | 721 | atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); |
738 | sfn->fn_flags = RTN_ROOT; | 722 | sfn->fn_flags = RTN_ROOT; |
739 | sfn->fn_sernum = fib6_new_sernum(); | 723 | sfn->fn_sernum = fib6_new_sernum(); |
740 | 724 | ||
@@ -776,9 +760,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
776 | err = fib6_add_rt2node(fn, rt, info); | 760 | err = fib6_add_rt2node(fn, rt, info); |
777 | 761 | ||
778 | if (err == 0) { | 762 | if (err == 0) { |
779 | fib6_start_gc(rt); | 763 | fib6_start_gc(info->nl_net, rt); |
780 | if (!(rt->rt6i_flags&RTF_CACHE)) | 764 | if (!(rt->rt6i_flags&RTF_CACHE)) |
781 | fib6_prune_clones(pn, rt); | 765 | fib6_prune_clones(info->nl_net, pn, rt); |
782 | } | 766 | } |
783 | 767 | ||
784 | out: | 768 | out: |
@@ -789,11 +773,11 @@ out: | |||
789 | * super-tree leaf node we have to find a new one for it. | 773 | * super-tree leaf node we have to find a new one for it. |
790 | */ | 774 | */ |
791 | if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { | 775 | if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { |
792 | pn->leaf = fib6_find_prefix(pn); | 776 | pn->leaf = fib6_find_prefix(info->nl_net, pn); |
793 | #if RT6_DEBUG >= 2 | 777 | #if RT6_DEBUG >= 2 |
794 | if (!pn->leaf) { | 778 | if (!pn->leaf) { |
795 | BUG_TRAP(pn->leaf != NULL); | 779 | BUG_TRAP(pn->leaf != NULL); |
796 | pn->leaf = &ip6_null_entry; | 780 | pn->leaf = info->nl_net->ipv6.ip6_null_entry; |
797 | } | 781 | } |
798 | #endif | 782 | #endif |
799 | atomic_inc(&pn->leaf->rt6i_ref); | 783 | atomic_inc(&pn->leaf->rt6i_ref); |
@@ -809,7 +793,7 @@ out: | |||
809 | */ | 793 | */ |
810 | st_failure: | 794 | st_failure: |
811 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) | 795 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) |
812 | fib6_repair_tree(fn); | 796 | fib6_repair_tree(info->nl_net, fn); |
813 | dst_free(&rt->u.dst); | 797 | dst_free(&rt->u.dst); |
814 | return err; | 798 | return err; |
815 | #endif | 799 | #endif |
@@ -975,10 +959,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root, | |||
975 | * | 959 | * |
976 | */ | 960 | */ |
977 | 961 | ||
978 | static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | 962 | static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn) |
979 | { | 963 | { |
980 | if (fn->fn_flags&RTN_ROOT) | 964 | if (fn->fn_flags&RTN_ROOT) |
981 | return &ip6_null_entry; | 965 | return net->ipv6.ip6_null_entry; |
982 | 966 | ||
983 | while(fn) { | 967 | while(fn) { |
984 | if(fn->left) | 968 | if(fn->left) |
@@ -997,7 +981,8 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | |||
997 | * is the node we want to try and remove. | 981 | * is the node we want to try and remove. |
998 | */ | 982 | */ |
999 | 983 | ||
1000 | static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) | 984 | static struct fib6_node *fib6_repair_tree(struct net *net, |
985 | struct fib6_node *fn) | ||
1001 | { | 986 | { |
1002 | int children; | 987 | int children; |
1003 | int nstate; | 988 | int nstate; |
@@ -1024,11 +1009,11 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) | |||
1024 | || (children && fn->fn_flags&RTN_ROOT) | 1009 | || (children && fn->fn_flags&RTN_ROOT) |
1025 | #endif | 1010 | #endif |
1026 | ) { | 1011 | ) { |
1027 | fn->leaf = fib6_find_prefix(fn); | 1012 | fn->leaf = fib6_find_prefix(net, fn); |
1028 | #if RT6_DEBUG >= 2 | 1013 | #if RT6_DEBUG >= 2 |
1029 | if (fn->leaf==NULL) { | 1014 | if (fn->leaf==NULL) { |
1030 | BUG_TRAP(fn->leaf); | 1015 | BUG_TRAP(fn->leaf); |
1031 | fn->leaf = &ip6_null_entry; | 1016 | fn->leaf = net->ipv6.ip6_null_entry; |
1032 | } | 1017 | } |
1033 | #endif | 1018 | #endif |
1034 | atomic_inc(&fn->leaf->rt6i_ref); | 1019 | atomic_inc(&fn->leaf->rt6i_ref); |
@@ -1101,14 +1086,15 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1101 | { | 1086 | { |
1102 | struct fib6_walker_t *w; | 1087 | struct fib6_walker_t *w; |
1103 | struct rt6_info *rt = *rtp; | 1088 | struct rt6_info *rt = *rtp; |
1089 | struct net *net = info->nl_net; | ||
1104 | 1090 | ||
1105 | RT6_TRACE("fib6_del_route\n"); | 1091 | RT6_TRACE("fib6_del_route\n"); |
1106 | 1092 | ||
1107 | /* Unlink it */ | 1093 | /* Unlink it */ |
1108 | *rtp = rt->u.dst.rt6_next; | 1094 | *rtp = rt->u.dst.rt6_next; |
1109 | rt->rt6i_node = NULL; | 1095 | rt->rt6i_node = NULL; |
1110 | rt6_stats.fib_rt_entries--; | 1096 | net->ipv6.rt6_stats->fib_rt_entries--; |
1111 | rt6_stats.fib_discarded_routes++; | 1097 | net->ipv6.rt6_stats->fib_discarded_routes++; |
1112 | 1098 | ||
1113 | /* Reset round-robin state, if necessary */ | 1099 | /* Reset round-robin state, if necessary */ |
1114 | if (fn->rr_ptr == rt) | 1100 | if (fn->rr_ptr == rt) |
@@ -1131,8 +1117,8 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1131 | /* If it was last route, expunge its radix tree node */ | 1117 | /* If it was last route, expunge its radix tree node */ |
1132 | if (fn->leaf == NULL) { | 1118 | if (fn->leaf == NULL) { |
1133 | fn->fn_flags &= ~RTN_RTINFO; | 1119 | fn->fn_flags &= ~RTN_RTINFO; |
1134 | rt6_stats.fib_route_nodes--; | 1120 | net->ipv6.rt6_stats->fib_route_nodes--; |
1135 | fn = fib6_repair_tree(fn); | 1121 | fn = fib6_repair_tree(net, fn); |
1136 | } | 1122 | } |
1137 | 1123 | ||
1138 | if (atomic_read(&rt->rt6i_ref) != 1) { | 1124 | if (atomic_read(&rt->rt6i_ref) != 1) { |
@@ -1144,7 +1130,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1144 | */ | 1130 | */ |
1145 | while (fn) { | 1131 | while (fn) { |
1146 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { | 1132 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { |
1147 | fn->leaf = fib6_find_prefix(fn); | 1133 | fn->leaf = fib6_find_prefix(net, fn); |
1148 | atomic_inc(&fn->leaf->rt6i_ref); | 1134 | atomic_inc(&fn->leaf->rt6i_ref); |
1149 | rt6_release(rt); | 1135 | rt6_release(rt); |
1150 | } | 1136 | } |
@@ -1160,6 +1146,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1160 | 1146 | ||
1161 | int fib6_del(struct rt6_info *rt, struct nl_info *info) | 1147 | int fib6_del(struct rt6_info *rt, struct nl_info *info) |
1162 | { | 1148 | { |
1149 | struct net *net = info->nl_net; | ||
1163 | struct fib6_node *fn = rt->rt6i_node; | 1150 | struct fib6_node *fn = rt->rt6i_node; |
1164 | struct rt6_info **rtp; | 1151 | struct rt6_info **rtp; |
1165 | 1152 | ||
@@ -1169,7 +1156,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1169 | return -ENOENT; | 1156 | return -ENOENT; |
1170 | } | 1157 | } |
1171 | #endif | 1158 | #endif |
1172 | if (fn == NULL || rt == &ip6_null_entry) | 1159 | if (fn == NULL || rt == net->ipv6.ip6_null_entry) |
1173 | return -ENOENT; | 1160 | return -ENOENT; |
1174 | 1161 | ||
1175 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); | 1162 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); |
@@ -1184,7 +1171,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1184 | pn = pn->parent; | 1171 | pn = pn->parent; |
1185 | } | 1172 | } |
1186 | #endif | 1173 | #endif |
1187 | fib6_prune_clones(pn, rt); | 1174 | fib6_prune_clones(info->nl_net, pn, rt); |
1188 | } | 1175 | } |
1189 | 1176 | ||
1190 | /* | 1177 | /* |
@@ -1314,12 +1301,12 @@ static int fib6_walk(struct fib6_walker_t *w) | |||
1314 | 1301 | ||
1315 | static int fib6_clean_node(struct fib6_walker_t *w) | 1302 | static int fib6_clean_node(struct fib6_walker_t *w) |
1316 | { | 1303 | { |
1317 | struct nl_info info = { | ||
1318 | .nl_net = &init_net, | ||
1319 | }; | ||
1320 | int res; | 1304 | int res; |
1321 | struct rt6_info *rt; | 1305 | struct rt6_info *rt; |
1322 | struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w); | 1306 | struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w); |
1307 | struct nl_info info = { | ||
1308 | .nl_net = c->net, | ||
1309 | }; | ||
1323 | 1310 | ||
1324 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { | 1311 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { |
1325 | res = c->func(rt, c->arg); | 1312 | res = c->func(rt, c->arg); |
@@ -1351,7 +1338,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) | |||
1351 | * ignoring pure split nodes) will be scanned. | 1338 | * ignoring pure split nodes) will be scanned. |
1352 | */ | 1339 | */ |
1353 | 1340 | ||
1354 | static void fib6_clean_tree(struct fib6_node *root, | 1341 | static void fib6_clean_tree(struct net *net, struct fib6_node *root, |
1355 | int (*func)(struct rt6_info *, void *arg), | 1342 | int (*func)(struct rt6_info *, void *arg), |
1356 | int prune, void *arg) | 1343 | int prune, void *arg) |
1357 | { | 1344 | { |
@@ -1362,23 +1349,26 @@ static void fib6_clean_tree(struct fib6_node *root, | |||
1362 | c.w.prune = prune; | 1349 | c.w.prune = prune; |
1363 | c.func = func; | 1350 | c.func = func; |
1364 | c.arg = arg; | 1351 | c.arg = arg; |
1352 | c.net = net; | ||
1365 | 1353 | ||
1366 | fib6_walk(&c.w); | 1354 | fib6_walk(&c.w); |
1367 | } | 1355 | } |
1368 | 1356 | ||
1369 | void fib6_clean_all(int (*func)(struct rt6_info *, void *arg), | 1357 | void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), |
1370 | int prune, void *arg) | 1358 | int prune, void *arg) |
1371 | { | 1359 | { |
1372 | struct fib6_table *table; | 1360 | struct fib6_table *table; |
1373 | struct hlist_node *node; | 1361 | struct hlist_node *node; |
1362 | struct hlist_head *head; | ||
1374 | unsigned int h; | 1363 | unsigned int h; |
1375 | 1364 | ||
1376 | rcu_read_lock(); | 1365 | rcu_read_lock(); |
1377 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { | 1366 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { |
1378 | hlist_for_each_entry_rcu(table, node, &fib_table_hash[h], | 1367 | head = &net->ipv6.fib_table_hash[h]; |
1379 | tb6_hlist) { | 1368 | hlist_for_each_entry_rcu(table, node, head, tb6_hlist) { |
1380 | write_lock_bh(&table->tb6_lock); | 1369 | write_lock_bh(&table->tb6_lock); |
1381 | fib6_clean_tree(&table->tb6_root, func, prune, arg); | 1370 | fib6_clean_tree(net, &table->tb6_root, |
1371 | func, prune, arg); | ||
1382 | write_unlock_bh(&table->tb6_lock); | 1372 | write_unlock_bh(&table->tb6_lock); |
1383 | } | 1373 | } |
1384 | } | 1374 | } |
@@ -1395,9 +1385,10 @@ static int fib6_prune_clone(struct rt6_info *rt, void *arg) | |||
1395 | return 0; | 1385 | return 0; |
1396 | } | 1386 | } |
1397 | 1387 | ||
1398 | static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt) | 1388 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, |
1389 | struct rt6_info *rt) | ||
1399 | { | 1390 | { |
1400 | fib6_clean_tree(fn, fib6_prune_clone, 1, rt); | 1391 | fib6_clean_tree(net, fn, fib6_prune_clone, 1, rt); |
1401 | } | 1392 | } |
1402 | 1393 | ||
1403 | /* | 1394 | /* |
@@ -1447,54 +1438,145 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1447 | 1438 | ||
1448 | static DEFINE_SPINLOCK(fib6_gc_lock); | 1439 | static DEFINE_SPINLOCK(fib6_gc_lock); |
1449 | 1440 | ||
1450 | void fib6_run_gc(unsigned long dummy) | 1441 | void fib6_run_gc(unsigned long expires, struct net *net) |
1451 | { | 1442 | { |
1452 | if (dummy != ~0UL) { | 1443 | if (expires != ~0UL) { |
1453 | spin_lock_bh(&fib6_gc_lock); | 1444 | spin_lock_bh(&fib6_gc_lock); |
1454 | gc_args.timeout = dummy ? (int)dummy : | 1445 | gc_args.timeout = expires ? (int)expires : |
1455 | init_net.ipv6.sysctl.ip6_rt_gc_interval; | 1446 | net->ipv6.sysctl.ip6_rt_gc_interval; |
1456 | } else { | 1447 | } else { |
1457 | local_bh_disable(); | 1448 | local_bh_disable(); |
1458 | if (!spin_trylock(&fib6_gc_lock)) { | 1449 | if (!spin_trylock(&fib6_gc_lock)) { |
1459 | mod_timer(&ip6_fib_timer, jiffies + HZ); | 1450 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ); |
1460 | local_bh_enable(); | 1451 | local_bh_enable(); |
1461 | return; | 1452 | return; |
1462 | } | 1453 | } |
1463 | gc_args.timeout = init_net.ipv6.sysctl.ip6_rt_gc_interval; | 1454 | gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval; |
1464 | } | 1455 | } |
1465 | gc_args.more = 0; | 1456 | gc_args.more = 0; |
1466 | 1457 | ||
1467 | ndisc_dst_gc(&gc_args.more); | 1458 | icmp6_dst_gc(&gc_args.more); |
1468 | fib6_clean_all(fib6_age, 0, NULL); | 1459 | |
1460 | fib6_clean_all(net, fib6_age, 0, NULL); | ||
1469 | 1461 | ||
1470 | if (gc_args.more) | 1462 | if (gc_args.more) |
1471 | mod_timer(&ip6_fib_timer, jiffies + | 1463 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
1472 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 1464 | net->ipv6.sysctl.ip6_rt_gc_interval); |
1473 | else { | 1465 | else { |
1474 | del_timer(&ip6_fib_timer); | 1466 | del_timer(net->ipv6.ip6_fib_timer); |
1475 | ip6_fib_timer.expires = 0; | 1467 | net->ipv6.ip6_fib_timer->expires = 0; |
1476 | } | 1468 | } |
1477 | spin_unlock_bh(&fib6_gc_lock); | 1469 | spin_unlock_bh(&fib6_gc_lock); |
1478 | } | 1470 | } |
1479 | 1471 | ||
1480 | int __init fib6_init(void) | 1472 | static void fib6_gc_timer_cb(unsigned long arg) |
1473 | { | ||
1474 | fib6_run_gc(0, (struct net *)arg); | ||
1475 | } | ||
1476 | |||
1477 | static int fib6_net_init(struct net *net) | ||
1481 | { | 1478 | { |
1482 | int ret; | 1479 | int ret; |
1480 | struct timer_list *timer; | ||
1481 | |||
1482 | ret = -ENOMEM; | ||
1483 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); | ||
1484 | if (!timer) | ||
1485 | goto out; | ||
1486 | |||
1487 | setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net); | ||
1488 | net->ipv6.ip6_fib_timer = timer; | ||
1489 | |||
1490 | net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL); | ||
1491 | if (!net->ipv6.rt6_stats) | ||
1492 | goto out_timer; | ||
1493 | |||
1494 | net->ipv6.fib_table_hash = | ||
1495 | kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ, | ||
1496 | GFP_KERNEL); | ||
1497 | if (!net->ipv6.fib_table_hash) | ||
1498 | goto out_rt6_stats; | ||
1499 | |||
1500 | net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl), | ||
1501 | GFP_KERNEL); | ||
1502 | if (!net->ipv6.fib6_main_tbl) | ||
1503 | goto out_fib_table_hash; | ||
1504 | |||
1505 | net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN; | ||
1506 | net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry; | ||
1507 | net->ipv6.fib6_main_tbl->tb6_root.fn_flags = | ||
1508 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | ||
1509 | |||
1510 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
1511 | net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl), | ||
1512 | GFP_KERNEL); | ||
1513 | if (!net->ipv6.fib6_local_tbl) | ||
1514 | goto out_fib6_main_tbl; | ||
1515 | net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL; | ||
1516 | net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry; | ||
1517 | net->ipv6.fib6_local_tbl->tb6_root.fn_flags = | ||
1518 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | ||
1519 | #endif | ||
1520 | fib6_tables_init(net); | ||
1521 | |||
1522 | ret = 0; | ||
1523 | out: | ||
1524 | return ret; | ||
1525 | |||
1526 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
1527 | out_fib6_main_tbl: | ||
1528 | kfree(net->ipv6.fib6_main_tbl); | ||
1529 | #endif | ||
1530 | out_fib_table_hash: | ||
1531 | kfree(net->ipv6.fib_table_hash); | ||
1532 | out_rt6_stats: | ||
1533 | kfree(net->ipv6.rt6_stats); | ||
1534 | out_timer: | ||
1535 | kfree(timer); | ||
1536 | goto out; | ||
1537 | } | ||
1538 | |||
1539 | static void fib6_net_exit(struct net *net) | ||
1540 | { | ||
1541 | rt6_ifdown(net, NULL); | ||
1542 | del_timer(net->ipv6.ip6_fib_timer); | ||
1543 | kfree(net->ipv6.ip6_fib_timer); | ||
1544 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
1545 | kfree(net->ipv6.fib6_local_tbl); | ||
1546 | #endif | ||
1547 | kfree(net->ipv6.fib6_main_tbl); | ||
1548 | kfree(net->ipv6.fib_table_hash); | ||
1549 | kfree(net->ipv6.rt6_stats); | ||
1550 | } | ||
1551 | |||
1552 | static struct pernet_operations fib6_net_ops = { | ||
1553 | .init = fib6_net_init, | ||
1554 | .exit = fib6_net_exit, | ||
1555 | }; | ||
1556 | |||
1557 | int __init fib6_init(void) | ||
1558 | { | ||
1559 | int ret = -ENOMEM; | ||
1560 | |||
1483 | fib6_node_kmem = kmem_cache_create("fib6_nodes", | 1561 | fib6_node_kmem = kmem_cache_create("fib6_nodes", |
1484 | sizeof(struct fib6_node), | 1562 | sizeof(struct fib6_node), |
1485 | 0, SLAB_HWCACHE_ALIGN, | 1563 | 0, SLAB_HWCACHE_ALIGN, |
1486 | NULL); | 1564 | NULL); |
1487 | if (!fib6_node_kmem) | 1565 | if (!fib6_node_kmem) |
1488 | return -ENOMEM; | 1566 | goto out; |
1489 | 1567 | ||
1490 | fib6_tables_init(); | 1568 | ret = register_pernet_subsys(&fib6_net_ops); |
1569 | if (ret) | ||
1570 | goto out_kmem_cache_create; | ||
1491 | 1571 | ||
1492 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); | 1572 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); |
1493 | if (ret) | 1573 | if (ret) |
1494 | goto out_kmem_cache_create; | 1574 | goto out_unregister_subsys; |
1495 | out: | 1575 | out: |
1496 | return ret; | 1576 | return ret; |
1497 | 1577 | ||
1578 | out_unregister_subsys: | ||
1579 | unregister_pernet_subsys(&fib6_net_ops); | ||
1498 | out_kmem_cache_create: | 1580 | out_kmem_cache_create: |
1499 | kmem_cache_destroy(fib6_node_kmem); | 1581 | kmem_cache_destroy(fib6_node_kmem); |
1500 | goto out; | 1582 | goto out; |
@@ -1502,6 +1584,6 @@ out_kmem_cache_create: | |||
1502 | 1584 | ||
1503 | void fib6_gc_cleanup(void) | 1585 | void fib6_gc_cleanup(void) |
1504 | { | 1586 | { |
1505 | del_timer(&ip6_fib_timer); | 1587 | unregister_pernet_subsys(&fib6_net_ops); |
1506 | kmem_cache_destroy(fib6_node_kmem); | 1588 | kmem_cache_destroy(fib6_node_kmem); |
1507 | } | 1589 | } |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 2b7d9ee98832..eb7a940310f4 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -62,23 +62,23 @@ static DEFINE_RWLOCK(ip6_fl_lock); | |||
62 | static DEFINE_RWLOCK(ip6_sk_fl_lock); | 62 | static DEFINE_RWLOCK(ip6_sk_fl_lock); |
63 | 63 | ||
64 | 64 | ||
65 | static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label) | 65 | static inline struct ip6_flowlabel *__fl_lookup(struct net *net, __be32 label) |
66 | { | 66 | { |
67 | struct ip6_flowlabel *fl; | 67 | struct ip6_flowlabel *fl; |
68 | 68 | ||
69 | for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) { | 69 | for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) { |
70 | if (fl->label == label) | 70 | if (fl->label == label && fl->fl_net == net) |
71 | return fl; | 71 | return fl; |
72 | } | 72 | } |
73 | return NULL; | 73 | return NULL; |
74 | } | 74 | } |
75 | 75 | ||
76 | static struct ip6_flowlabel * fl_lookup(__be32 label) | 76 | static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label) |
77 | { | 77 | { |
78 | struct ip6_flowlabel *fl; | 78 | struct ip6_flowlabel *fl; |
79 | 79 | ||
80 | read_lock_bh(&ip6_fl_lock); | 80 | read_lock_bh(&ip6_fl_lock); |
81 | fl = __fl_lookup(label); | 81 | fl = __fl_lookup(net, label); |
82 | if (fl) | 82 | if (fl) |
83 | atomic_inc(&fl->users); | 83 | atomic_inc(&fl->users); |
84 | read_unlock_bh(&ip6_fl_lock); | 84 | read_unlock_bh(&ip6_fl_lock); |
@@ -88,8 +88,10 @@ static struct ip6_flowlabel * fl_lookup(__be32 label) | |||
88 | 88 | ||
89 | static void fl_free(struct ip6_flowlabel *fl) | 89 | static void fl_free(struct ip6_flowlabel *fl) |
90 | { | 90 | { |
91 | if (fl) | 91 | if (fl) { |
92 | release_net(fl->fl_net); | ||
92 | kfree(fl->opt); | 93 | kfree(fl->opt); |
94 | } | ||
93 | kfree(fl); | 95 | kfree(fl); |
94 | } | 96 | } |
95 | 97 | ||
@@ -112,7 +114,6 @@ static void fl_release(struct ip6_flowlabel *fl) | |||
112 | time_after(ip6_fl_gc_timer.expires, ttd)) | 114 | time_after(ip6_fl_gc_timer.expires, ttd)) |
113 | mod_timer(&ip6_fl_gc_timer, ttd); | 115 | mod_timer(&ip6_fl_gc_timer, ttd); |
114 | } | 116 | } |
115 | |||
116 | write_unlock_bh(&ip6_fl_lock); | 117 | write_unlock_bh(&ip6_fl_lock); |
117 | } | 118 | } |
118 | 119 | ||
@@ -148,13 +149,34 @@ static void ip6_fl_gc(unsigned long dummy) | |||
148 | if (!sched && atomic_read(&fl_size)) | 149 | if (!sched && atomic_read(&fl_size)) |
149 | sched = now + FL_MAX_LINGER; | 150 | sched = now + FL_MAX_LINGER; |
150 | if (sched) { | 151 | if (sched) { |
151 | ip6_fl_gc_timer.expires = sched; | 152 | mod_timer(&ip6_fl_gc_timer, sched); |
152 | add_timer(&ip6_fl_gc_timer); | 153 | } |
154 | write_unlock(&ip6_fl_lock); | ||
155 | } | ||
156 | |||
157 | static void ip6_fl_purge(struct net *net) | ||
158 | { | ||
159 | int i; | ||
160 | |||
161 | write_lock(&ip6_fl_lock); | ||
162 | for (i = 0; i <= FL_HASH_MASK; i++) { | ||
163 | struct ip6_flowlabel *fl, **flp; | ||
164 | flp = &fl_ht[i]; | ||
165 | while ((fl = *flp) != NULL) { | ||
166 | if (fl->fl_net == net && atomic_read(&fl->users) == 0) { | ||
167 | *flp = fl->next; | ||
168 | fl_free(fl); | ||
169 | atomic_dec(&fl_size); | ||
170 | continue; | ||
171 | } | ||
172 | flp = &fl->next; | ||
173 | } | ||
153 | } | 174 | } |
154 | write_unlock(&ip6_fl_lock); | 175 | write_unlock(&ip6_fl_lock); |
155 | } | 176 | } |
156 | 177 | ||
157 | static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) | 178 | static struct ip6_flowlabel *fl_intern(struct net *net, |
179 | struct ip6_flowlabel *fl, __be32 label) | ||
158 | { | 180 | { |
159 | struct ip6_flowlabel *lfl; | 181 | struct ip6_flowlabel *lfl; |
160 | 182 | ||
@@ -165,7 +187,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) | |||
165 | for (;;) { | 187 | for (;;) { |
166 | fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; | 188 | fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; |
167 | if (fl->label) { | 189 | if (fl->label) { |
168 | lfl = __fl_lookup(fl->label); | 190 | lfl = __fl_lookup(net, fl->label); |
169 | if (lfl == NULL) | 191 | if (lfl == NULL) |
170 | break; | 192 | break; |
171 | } | 193 | } |
@@ -179,7 +201,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) | |||
179 | * done in ipv6_flowlabel_opt - sock is locked, so new entry | 201 | * done in ipv6_flowlabel_opt - sock is locked, so new entry |
180 | * with the same label can only appear on another sock | 202 | * with the same label can only appear on another sock |
181 | */ | 203 | */ |
182 | lfl = __fl_lookup(fl->label); | 204 | lfl = __fl_lookup(net, fl->label); |
183 | if (lfl != NULL) { | 205 | if (lfl != NULL) { |
184 | atomic_inc(&lfl->users); | 206 | atomic_inc(&lfl->users); |
185 | write_unlock_bh(&ip6_fl_lock); | 207 | write_unlock_bh(&ip6_fl_lock); |
@@ -298,7 +320,8 @@ static int fl6_renew(struct ip6_flowlabel *fl, unsigned long linger, unsigned lo | |||
298 | } | 320 | } |
299 | 321 | ||
300 | static struct ip6_flowlabel * | 322 | static struct ip6_flowlabel * |
301 | fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *err_p) | 323 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, |
324 | int optlen, int *err_p) | ||
302 | { | 325 | { |
303 | struct ip6_flowlabel *fl; | 326 | struct ip6_flowlabel *fl; |
304 | int olen; | 327 | int olen; |
@@ -343,6 +366,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int * | |||
343 | } | 366 | } |
344 | } | 367 | } |
345 | 368 | ||
369 | fl->fl_net = hold_net(net); | ||
346 | fl->expires = jiffies; | 370 | fl->expires = jiffies; |
347 | err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); | 371 | err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); |
348 | if (err) | 372 | if (err) |
@@ -441,6 +465,7 @@ static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl, | |||
441 | int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | 465 | int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) |
442 | { | 466 | { |
443 | int err; | 467 | int err; |
468 | struct net *net = sock_net(sk); | ||
444 | struct ipv6_pinfo *np = inet6_sk(sk); | 469 | struct ipv6_pinfo *np = inet6_sk(sk); |
445 | struct in6_flowlabel_req freq; | 470 | struct in6_flowlabel_req freq; |
446 | struct ipv6_fl_socklist *sfl1=NULL; | 471 | struct ipv6_fl_socklist *sfl1=NULL; |
@@ -483,7 +508,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
483 | read_unlock_bh(&ip6_sk_fl_lock); | 508 | read_unlock_bh(&ip6_sk_fl_lock); |
484 | 509 | ||
485 | if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { | 510 | if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { |
486 | fl = fl_lookup(freq.flr_label); | 511 | fl = fl_lookup(net, freq.flr_label); |
487 | if (fl) { | 512 | if (fl) { |
488 | err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); | 513 | err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); |
489 | fl_release(fl); | 514 | fl_release(fl); |
@@ -496,7 +521,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
496 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) | 521 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) |
497 | return -EINVAL; | 522 | return -EINVAL; |
498 | 523 | ||
499 | fl = fl_create(&freq, optval, optlen, &err); | 524 | fl = fl_create(net, &freq, optval, optlen, &err); |
500 | if (fl == NULL) | 525 | if (fl == NULL) |
501 | return err; | 526 | return err; |
502 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); | 527 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); |
@@ -518,7 +543,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
518 | read_unlock_bh(&ip6_sk_fl_lock); | 543 | read_unlock_bh(&ip6_sk_fl_lock); |
519 | 544 | ||
520 | if (fl1 == NULL) | 545 | if (fl1 == NULL) |
521 | fl1 = fl_lookup(freq.flr_label); | 546 | fl1 = fl_lookup(net, freq.flr_label); |
522 | if (fl1) { | 547 | if (fl1) { |
523 | recheck: | 548 | recheck: |
524 | err = -EEXIST; | 549 | err = -EEXIST; |
@@ -559,7 +584,7 @@ release: | |||
559 | if (sfl1 == NULL || (err = mem_check(sk)) != 0) | 584 | if (sfl1 == NULL || (err = mem_check(sk)) != 0) |
560 | goto done; | 585 | goto done; |
561 | 586 | ||
562 | fl1 = fl_intern(fl, freq.flr_label); | 587 | fl1 = fl_intern(net, fl, freq.flr_label); |
563 | if (fl1 != NULL) | 588 | if (fl1 != NULL) |
564 | goto recheck; | 589 | goto recheck; |
565 | 590 | ||
@@ -586,6 +611,7 @@ done: | |||
586 | #ifdef CONFIG_PROC_FS | 611 | #ifdef CONFIG_PROC_FS |
587 | 612 | ||
588 | struct ip6fl_iter_state { | 613 | struct ip6fl_iter_state { |
614 | struct seq_net_private p; | ||
589 | int bucket; | 615 | int bucket; |
590 | }; | 616 | }; |
591 | 617 | ||
@@ -595,12 +621,15 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq) | |||
595 | { | 621 | { |
596 | struct ip6_flowlabel *fl = NULL; | 622 | struct ip6_flowlabel *fl = NULL; |
597 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 623 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
624 | struct net *net = seq_file_net(seq); | ||
598 | 625 | ||
599 | for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { | 626 | for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { |
600 | if (fl_ht[state->bucket]) { | 627 | fl = fl_ht[state->bucket]; |
601 | fl = fl_ht[state->bucket]; | 628 | |
629 | while (fl && fl->fl_net != net) | ||
630 | fl = fl->next; | ||
631 | if (fl) | ||
602 | break; | 632 | break; |
603 | } | ||
604 | } | 633 | } |
605 | return fl; | 634 | return fl; |
606 | } | 635 | } |
@@ -608,12 +637,18 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq) | |||
608 | static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl) | 637 | static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl) |
609 | { | 638 | { |
610 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 639 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
640 | struct net *net = seq_file_net(seq); | ||
611 | 641 | ||
612 | fl = fl->next; | 642 | fl = fl->next; |
643 | try_again: | ||
644 | while (fl && fl->fl_net != net) | ||
645 | fl = fl->next; | ||
646 | |||
613 | while (!fl) { | 647 | while (!fl) { |
614 | if (++state->bucket <= FL_HASH_MASK) | 648 | if (++state->bucket <= FL_HASH_MASK) { |
615 | fl = fl_ht[state->bucket]; | 649 | fl = fl_ht[state->bucket]; |
616 | else | 650 | goto try_again; |
651 | } else | ||
617 | break; | 652 | break; |
618 | } | 653 | } |
619 | return fl; | 654 | return fl; |
@@ -683,8 +718,8 @@ static const struct seq_operations ip6fl_seq_ops = { | |||
683 | 718 | ||
684 | static int ip6fl_seq_open(struct inode *inode, struct file *file) | 719 | static int ip6fl_seq_open(struct inode *inode, struct file *file) |
685 | { | 720 | { |
686 | return seq_open_private(file, &ip6fl_seq_ops, | 721 | return seq_open_net(inode, file, &ip6fl_seq_ops, |
687 | sizeof(struct ip6fl_iter_state)); | 722 | sizeof(struct ip6fl_iter_state)); |
688 | } | 723 | } |
689 | 724 | ||
690 | static const struct file_operations ip6fl_seq_fops = { | 725 | static const struct file_operations ip6fl_seq_fops = { |
@@ -692,12 +727,13 @@ static const struct file_operations ip6fl_seq_fops = { | |||
692 | .open = ip6fl_seq_open, | 727 | .open = ip6fl_seq_open, |
693 | .read = seq_read, | 728 | .read = seq_read, |
694 | .llseek = seq_lseek, | 729 | .llseek = seq_lseek, |
695 | .release = seq_release_private, | 730 | .release = seq_release_net, |
696 | }; | 731 | }; |
697 | 732 | ||
698 | static int ip6_flowlabel_proc_init(struct net *net) | 733 | static int ip6_flowlabel_proc_init(struct net *net) |
699 | { | 734 | { |
700 | if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops)) | 735 | if (!proc_net_fops_create(net, "ip6_flowlabel", |
736 | S_IRUGO, &ip6fl_seq_fops)) | ||
701 | return -ENOMEM; | 737 | return -ENOMEM; |
702 | return 0; | 738 | return 0; |
703 | } | 739 | } |
@@ -717,13 +753,24 @@ static inline void ip6_flowlabel_proc_fini(struct net *net) | |||
717 | } | 753 | } |
718 | #endif | 754 | #endif |
719 | 755 | ||
756 | static inline void ip6_flowlabel_net_exit(struct net *net) | ||
757 | { | ||
758 | ip6_fl_purge(net); | ||
759 | ip6_flowlabel_proc_fini(net); | ||
760 | } | ||
761 | |||
762 | static struct pernet_operations ip6_flowlabel_net_ops = { | ||
763 | .init = ip6_flowlabel_proc_init, | ||
764 | .exit = ip6_flowlabel_net_exit, | ||
765 | }; | ||
766 | |||
720 | int ip6_flowlabel_init(void) | 767 | int ip6_flowlabel_init(void) |
721 | { | 768 | { |
722 | return ip6_flowlabel_proc_init(&init_net); | 769 | return register_pernet_subsys(&ip6_flowlabel_net_ops); |
723 | } | 770 | } |
724 | 771 | ||
725 | void ip6_flowlabel_cleanup(void) | 772 | void ip6_flowlabel_cleanup(void) |
726 | { | 773 | { |
727 | del_timer(&ip6_fl_gc_timer); | 774 | del_timer(&ip6_fl_gc_timer); |
728 | ip6_flowlabel_proc_fini(&init_net); | 775 | unregister_pernet_subsys(&ip6_flowlabel_net_ops); |
729 | } | 776 | } |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 178aebc0427a..7e36269826ba 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -61,11 +61,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
61 | u32 pkt_len; | 61 | u32 pkt_len; |
62 | struct inet6_dev *idev; | 62 | struct inet6_dev *idev; |
63 | 63 | ||
64 | if (dev->nd_net != &init_net) { | ||
65 | kfree_skb(skb); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | if (skb->pkt_type == PACKET_OTHERHOST) { | 64 | if (skb->pkt_type == PACKET_OTHERHOST) { |
70 | kfree_skb(skb); | 65 | kfree_skb(skb); |
71 | return 0; | 66 | return 0; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 8b67ca07467d..a8b4da25b0a7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -237,9 +237,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
237 | if (np) | 237 | if (np) |
238 | hlimit = np->hop_limit; | 238 | hlimit = np->hop_limit; |
239 | if (hlimit < 0) | 239 | if (hlimit < 0) |
240 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 240 | hlimit = ip6_dst_hoplimit(dst); |
241 | if (hlimit < 0) | ||
242 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
243 | 241 | ||
244 | tclass = -1; | 242 | tclass = -1; |
245 | if (np) | 243 | if (np) |
@@ -404,6 +402,7 @@ int ip6_forward(struct sk_buff *skb) | |||
404 | struct dst_entry *dst = skb->dst; | 402 | struct dst_entry *dst = skb->dst; |
405 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 403 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
406 | struct inet6_skb_parm *opt = IP6CB(skb); | 404 | struct inet6_skb_parm *opt = IP6CB(skb); |
405 | struct net *net = dev_net(dst->dev); | ||
407 | 406 | ||
408 | if (ipv6_devconf.forwarding == 0) | 407 | if (ipv6_devconf.forwarding == 0) |
409 | goto error; | 408 | goto error; |
@@ -450,7 +449,7 @@ int ip6_forward(struct sk_buff *skb) | |||
450 | 449 | ||
451 | /* XXX: idev->cnf.proxy_ndp? */ | 450 | /* XXX: idev->cnf.proxy_ndp? */ |
452 | if (ipv6_devconf.proxy_ndp && | 451 | if (ipv6_devconf.proxy_ndp && |
453 | pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) { | 452 | pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) { |
454 | int proxied = ip6_forward_proxy_check(skb); | 453 | int proxied = ip6_forward_proxy_check(skb); |
455 | if (proxied > 0) | 454 | if (proxied > 0) |
456 | return ip6_input(skb); | 455 | return ip6_input(skb); |
@@ -596,7 +595,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
596 | 595 | ||
597 | return offset; | 596 | return offset; |
598 | } | 597 | } |
599 | EXPORT_SYMBOL_GPL(ip6_find_1stfragopt); | ||
600 | 598 | ||
601 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 599 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
602 | { | 600 | { |
@@ -912,15 +910,19 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
912 | struct dst_entry **dst, struct flowi *fl) | 910 | struct dst_entry **dst, struct flowi *fl) |
913 | { | 911 | { |
914 | int err; | 912 | int err; |
913 | struct net *net = sock_net(sk); | ||
915 | 914 | ||
916 | if (*dst == NULL) | 915 | if (*dst == NULL) |
917 | *dst = ip6_route_output(sk, fl); | 916 | *dst = ip6_route_output(net, sk, fl); |
918 | 917 | ||
919 | if ((err = (*dst)->error)) | 918 | if ((err = (*dst)->error)) |
920 | goto out_err_release; | 919 | goto out_err_release; |
921 | 920 | ||
922 | if (ipv6_addr_any(&fl->fl6_src)) { | 921 | if (ipv6_addr_any(&fl->fl6_src)) { |
923 | err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); | 922 | err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev, |
923 | &fl->fl6_dst, | ||
924 | sk ? inet6_sk(sk)->srcprefs : 0, | ||
925 | &fl->fl6_src); | ||
924 | if (err) | 926 | if (err) |
925 | goto out_err_release; | 927 | goto out_err_release; |
926 | } | 928 | } |
@@ -939,7 +941,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
939 | struct flowi fl_gw; | 941 | struct flowi fl_gw; |
940 | int redirect; | 942 | int redirect; |
941 | 943 | ||
942 | ifp = ipv6_get_ifaddr(&init_net, &fl->fl6_src, | 944 | ifp = ipv6_get_ifaddr(net, &fl->fl6_src, |
943 | (*dst)->dev, 1); | 945 | (*dst)->dev, 1); |
944 | 946 | ||
945 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); | 947 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); |
@@ -954,7 +956,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
954 | dst_release(*dst); | 956 | dst_release(*dst); |
955 | memcpy(&fl_gw, fl, sizeof(struct flowi)); | 957 | memcpy(&fl_gw, fl, sizeof(struct flowi)); |
956 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); | 958 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); |
957 | *dst = ip6_route_output(sk, &fl_gw); | 959 | *dst = ip6_route_output(net, sk, &fl_gw); |
958 | if ((err = (*dst)->error)) | 960 | if ((err = (*dst)->error)) |
959 | goto out_err_release; | 961 | goto out_err_release; |
960 | } | 962 | } |
@@ -1113,7 +1115,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1113 | /* need source address above miyazawa*/ | 1115 | /* need source address above miyazawa*/ |
1114 | } | 1116 | } |
1115 | dst_hold(&rt->u.dst); | 1117 | dst_hold(&rt->u.dst); |
1116 | np->cork.rt = rt; | 1118 | inet->cork.dst = &rt->u.dst; |
1117 | inet->cork.fl = *fl; | 1119 | inet->cork.fl = *fl; |
1118 | np->cork.hop_limit = hlimit; | 1120 | np->cork.hop_limit = hlimit; |
1119 | np->cork.tclass = tclass; | 1121 | np->cork.tclass = tclass; |
@@ -1134,7 +1136,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1134 | length += exthdrlen; | 1136 | length += exthdrlen; |
1135 | transhdrlen += exthdrlen; | 1137 | transhdrlen += exthdrlen; |
1136 | } else { | 1138 | } else { |
1137 | rt = np->cork.rt; | 1139 | rt = (struct rt6_info *)inet->cork.dst; |
1138 | fl = &inet->cork.fl; | 1140 | fl = &inet->cork.fl; |
1139 | if (inet->cork.flags & IPCORK_OPT) | 1141 | if (inet->cork.flags & IPCORK_OPT) |
1140 | opt = np->cork.opt; | 1142 | opt = np->cork.opt; |
@@ -1379,9 +1381,9 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) | |||
1379 | inet->cork.flags &= ~IPCORK_OPT; | 1381 | inet->cork.flags &= ~IPCORK_OPT; |
1380 | kfree(np->cork.opt); | 1382 | kfree(np->cork.opt); |
1381 | np->cork.opt = NULL; | 1383 | np->cork.opt = NULL; |
1382 | if (np->cork.rt) { | 1384 | if (inet->cork.dst) { |
1383 | dst_release(&np->cork.rt->u.dst); | 1385 | dst_release(inet->cork.dst); |
1384 | np->cork.rt = NULL; | 1386 | inet->cork.dst = NULL; |
1385 | inet->cork.flags &= ~IPCORK_ALLFRAG; | 1387 | inet->cork.flags &= ~IPCORK_ALLFRAG; |
1386 | } | 1388 | } |
1387 | memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); | 1389 | memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); |
@@ -1396,7 +1398,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1396 | struct ipv6_pinfo *np = inet6_sk(sk); | 1398 | struct ipv6_pinfo *np = inet6_sk(sk); |
1397 | struct ipv6hdr *hdr; | 1399 | struct ipv6hdr *hdr; |
1398 | struct ipv6_txoptions *opt = np->cork.opt; | 1400 | struct ipv6_txoptions *opt = np->cork.opt; |
1399 | struct rt6_info *rt = np->cork.rt; | 1401 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; |
1400 | struct flowi *fl = &inet->cork.fl; | 1402 | struct flowi *fl = &inet->cork.fl; |
1401 | unsigned char proto = fl->proto; | 1403 | unsigned char proto = fl->proto; |
1402 | int err = 0; | 1404 | int err = 0; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 78f438880923..61517fe0c57c 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -60,7 +60,7 @@ MODULE_LICENSE("GPL"); | |||
60 | #define IPV6_TLV_TEL_DST_SIZE 8 | 60 | #define IPV6_TLV_TEL_DST_SIZE 8 |
61 | 61 | ||
62 | #ifdef IP6_TNL_DEBUG | 62 | #ifdef IP6_TNL_DEBUG |
63 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__) | 63 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) |
64 | #else | 64 | #else |
65 | #define IP6_TNL_TRACE(x...) do {;} while(0) | 65 | #define IP6_TNL_TRACE(x...) do {;} while(0) |
66 | #endif | 66 | #endif |
@@ -602,7 +602,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
602 | skb_reset_network_header(skb2); | 602 | skb_reset_network_header(skb2); |
603 | 603 | ||
604 | /* Try to guess incoming interface */ | 604 | /* Try to guess incoming interface */ |
605 | rt = rt6_lookup(&ipv6_hdr(skb2)->saddr, NULL, 0, 0); | 605 | rt = rt6_lookup(&init_net, &ipv6_hdr(skb2)->saddr, NULL, 0, 0); |
606 | 606 | ||
607 | if (rt && rt->rt6i_dev) | 607 | if (rt && rt->rt6i_dev) |
608 | skb2->dev = rt->rt6i_dev; | 608 | skb2->dev = rt->rt6i_dev; |
@@ -847,7 +847,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
847 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 847 | if ((dst = ip6_tnl_dst_check(t)) != NULL) |
848 | dst_hold(dst); | 848 | dst_hold(dst); |
849 | else { | 849 | else { |
850 | dst = ip6_route_output(NULL, fl); | 850 | dst = ip6_route_output(&init_net, NULL, fl); |
851 | 851 | ||
852 | if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0) | 852 | if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0) |
853 | goto tx_err_link_failure; | 853 | goto tx_err_link_failure; |
@@ -1112,7 +1112,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1112 | int strict = (ipv6_addr_type(&p->raddr) & | 1112 | int strict = (ipv6_addr_type(&p->raddr) & |
1113 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); | 1113 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); |
1114 | 1114 | ||
1115 | struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr, | 1115 | struct rt6_info *rt = rt6_lookup(&init_net, &p->raddr, &p->laddr, |
1116 | p->link, strict); | 1116 | p->link, strict); |
1117 | 1117 | ||
1118 | if (rt == NULL) | 1118 | if (rt == NULL) |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index bf2a686aa13d..d3d93d752e10 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -57,118 +57,6 @@ | |||
57 | 57 | ||
58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; | 58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; |
59 | 59 | ||
60 | static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb, | ||
61 | int proto) | ||
62 | { | ||
63 | struct inet6_protocol *ops = NULL; | ||
64 | |||
65 | for (;;) { | ||
66 | struct ipv6_opt_hdr *opth; | ||
67 | int len; | ||
68 | |||
69 | if (proto != NEXTHDR_HOP) { | ||
70 | ops = rcu_dereference(inet6_protos[proto]); | ||
71 | |||
72 | if (unlikely(!ops)) | ||
73 | break; | ||
74 | |||
75 | if (!(ops->flags & INET6_PROTO_GSO_EXTHDR)) | ||
76 | break; | ||
77 | } | ||
78 | |||
79 | if (unlikely(!pskb_may_pull(skb, 8))) | ||
80 | break; | ||
81 | |||
82 | opth = (void *)skb->data; | ||
83 | len = opth->hdrlen * 8 + 8; | ||
84 | |||
85 | if (unlikely(!pskb_may_pull(skb, len))) | ||
86 | break; | ||
87 | |||
88 | proto = opth->nexthdr; | ||
89 | __skb_pull(skb, len); | ||
90 | } | ||
91 | |||
92 | return ops; | ||
93 | } | ||
94 | |||
95 | static int ipv6_gso_send_check(struct sk_buff *skb) | ||
96 | { | ||
97 | struct ipv6hdr *ipv6h; | ||
98 | struct inet6_protocol *ops; | ||
99 | int err = -EINVAL; | ||
100 | |||
101 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
102 | goto out; | ||
103 | |||
104 | ipv6h = ipv6_hdr(skb); | ||
105 | __skb_pull(skb, sizeof(*ipv6h)); | ||
106 | err = -EPROTONOSUPPORT; | ||
107 | |||
108 | rcu_read_lock(); | ||
109 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | ||
110 | if (likely(ops && ops->gso_send_check)) { | ||
111 | skb_reset_transport_header(skb); | ||
112 | err = ops->gso_send_check(skb); | ||
113 | } | ||
114 | rcu_read_unlock(); | ||
115 | |||
116 | out: | ||
117 | return err; | ||
118 | } | ||
119 | |||
120 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | ||
121 | { | ||
122 | struct sk_buff *segs = ERR_PTR(-EINVAL); | ||
123 | struct ipv6hdr *ipv6h; | ||
124 | struct inet6_protocol *ops; | ||
125 | |||
126 | if (!(features & NETIF_F_V6_CSUM)) | ||
127 | features &= ~NETIF_F_SG; | ||
128 | |||
129 | if (unlikely(skb_shinfo(skb)->gso_type & | ||
130 | ~(SKB_GSO_UDP | | ||
131 | SKB_GSO_DODGY | | ||
132 | SKB_GSO_TCP_ECN | | ||
133 | SKB_GSO_TCPV6 | | ||
134 | 0))) | ||
135 | goto out; | ||
136 | |||
137 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
138 | goto out; | ||
139 | |||
140 | ipv6h = ipv6_hdr(skb); | ||
141 | __skb_pull(skb, sizeof(*ipv6h)); | ||
142 | segs = ERR_PTR(-EPROTONOSUPPORT); | ||
143 | |||
144 | rcu_read_lock(); | ||
145 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | ||
146 | if (likely(ops && ops->gso_segment)) { | ||
147 | skb_reset_transport_header(skb); | ||
148 | segs = ops->gso_segment(skb, features); | ||
149 | } | ||
150 | rcu_read_unlock(); | ||
151 | |||
152 | if (unlikely(IS_ERR(segs))) | ||
153 | goto out; | ||
154 | |||
155 | for (skb = segs; skb; skb = skb->next) { | ||
156 | ipv6h = ipv6_hdr(skb); | ||
157 | ipv6h->payload_len = htons(skb->len - skb->mac_len - | ||
158 | sizeof(*ipv6h)); | ||
159 | } | ||
160 | |||
161 | out: | ||
162 | return segs; | ||
163 | } | ||
164 | |||
165 | static struct packet_type ipv6_packet_type = { | ||
166 | .type = __constant_htons(ETH_P_IPV6), | ||
167 | .func = ipv6_rcv, | ||
168 | .gso_send_check = ipv6_gso_send_check, | ||
169 | .gso_segment = ipv6_gso_segment, | ||
170 | }; | ||
171 | |||
172 | struct ip6_ra_chain *ip6_ra_chain; | 60 | struct ip6_ra_chain *ip6_ra_chain; |
173 | DEFINE_RWLOCK(ip6_ra_lock); | 61 | DEFINE_RWLOCK(ip6_ra_lock); |
174 | 62 | ||
@@ -219,6 +107,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
219 | char __user *optval, int optlen) | 107 | char __user *optval, int optlen) |
220 | { | 108 | { |
221 | struct ipv6_pinfo *np = inet6_sk(sk); | 109 | struct ipv6_pinfo *np = inet6_sk(sk); |
110 | struct net *net = sock_net(sk); | ||
222 | int val, valbool; | 111 | int val, valbool; |
223 | int retv = -ENOPROTOOPT; | 112 | int retv = -ENOPROTOOPT; |
224 | 113 | ||
@@ -544,7 +433,7 @@ done: | |||
544 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) | 433 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) |
545 | goto e_inval; | 434 | goto e_inval; |
546 | 435 | ||
547 | if (__dev_get_by_index(&init_net, val) == NULL) { | 436 | if (__dev_get_by_index(net, val) == NULL) { |
548 | retv = -ENODEV; | 437 | retv = -ENODEV; |
549 | break; | 438 | break; |
550 | } | 439 | } |
@@ -728,7 +617,67 @@ done: | |||
728 | retv = xfrm_user_policy(sk, optname, optval, optlen); | 617 | retv = xfrm_user_policy(sk, optname, optval, optlen); |
729 | break; | 618 | break; |
730 | 619 | ||
620 | case IPV6_ADDR_PREFERENCES: | ||
621 | { | ||
622 | unsigned int pref = 0; | ||
623 | unsigned int prefmask = ~0; | ||
624 | |||
625 | retv = -EINVAL; | ||
626 | |||
627 | /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ | ||
628 | switch (val & (IPV6_PREFER_SRC_PUBLIC| | ||
629 | IPV6_PREFER_SRC_TMP| | ||
630 | IPV6_PREFER_SRC_PUBTMP_DEFAULT)) { | ||
631 | case IPV6_PREFER_SRC_PUBLIC: | ||
632 | pref |= IPV6_PREFER_SRC_PUBLIC; | ||
633 | break; | ||
634 | case IPV6_PREFER_SRC_TMP: | ||
635 | pref |= IPV6_PREFER_SRC_TMP; | ||
636 | break; | ||
637 | case IPV6_PREFER_SRC_PUBTMP_DEFAULT: | ||
638 | break; | ||
639 | case 0: | ||
640 | goto pref_skip_pubtmp; | ||
641 | default: | ||
642 | goto e_inval; | ||
643 | } | ||
644 | |||
645 | prefmask &= ~(IPV6_PREFER_SRC_PUBLIC| | ||
646 | IPV6_PREFER_SRC_TMP); | ||
647 | pref_skip_pubtmp: | ||
648 | |||
649 | /* check HOME/COA conflicts */ | ||
650 | switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) { | ||
651 | case IPV6_PREFER_SRC_HOME: | ||
652 | break; | ||
653 | case IPV6_PREFER_SRC_COA: | ||
654 | pref |= IPV6_PREFER_SRC_COA; | ||
655 | case 0: | ||
656 | goto pref_skip_coa; | ||
657 | default: | ||
658 | goto e_inval; | ||
659 | } | ||
660 | |||
661 | prefmask &= ~IPV6_PREFER_SRC_COA; | ||
662 | pref_skip_coa: | ||
663 | |||
664 | /* check CGA/NONCGA conflicts */ | ||
665 | switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) { | ||
666 | case IPV6_PREFER_SRC_CGA: | ||
667 | case IPV6_PREFER_SRC_NONCGA: | ||
668 | case 0: | ||
669 | break; | ||
670 | default: | ||
671 | goto e_inval; | ||
672 | } | ||
673 | |||
674 | np->srcprefs = (np->srcprefs & prefmask) | pref; | ||
675 | retv = 0; | ||
676 | |||
677 | break; | ||
678 | } | ||
731 | } | 679 | } |
680 | |||
732 | release_sock(sk); | 681 | release_sock(sk); |
733 | 682 | ||
734 | return retv; | 683 | return retv; |
@@ -1015,9 +964,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1015 | dst = sk_dst_get(sk); | 964 | dst = sk_dst_get(sk); |
1016 | if (dst) { | 965 | if (dst) { |
1017 | if (val < 0) | 966 | if (val < 0) |
1018 | val = dst_metric(dst, RTAX_HOPLIMIT); | 967 | val = ip6_dst_hoplimit(dst); |
1019 | if (val < 0) | ||
1020 | val = ipv6_get_hoplimit(dst->dev); | ||
1021 | dst_release(dst); | 968 | dst_release(dst); |
1022 | } | 969 | } |
1023 | if (val < 0) | 970 | if (val < 0) |
@@ -1045,6 +992,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1045 | val = np->sndflow; | 992 | val = np->sndflow; |
1046 | break; | 993 | break; |
1047 | 994 | ||
995 | case IPV6_ADDR_PREFERENCES: | ||
996 | val = 0; | ||
997 | |||
998 | if (np->srcprefs & IPV6_PREFER_SRC_TMP) | ||
999 | val |= IPV6_PREFER_SRC_TMP; | ||
1000 | else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC) | ||
1001 | val |= IPV6_PREFER_SRC_PUBLIC; | ||
1002 | else { | ||
1003 | /* XXX: should we return system default? */ | ||
1004 | val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT; | ||
1005 | } | ||
1006 | |||
1007 | if (np->srcprefs & IPV6_PREFER_SRC_COA) | ||
1008 | val |= IPV6_PREFER_SRC_COA; | ||
1009 | else | ||
1010 | val |= IPV6_PREFER_SRC_HOME; | ||
1011 | break; | ||
1012 | |||
1048 | default: | 1013 | default: |
1049 | return -ENOPROTOOPT; | 1014 | return -ENOPROTOOPT; |
1050 | } | 1015 | } |
@@ -1128,13 +1093,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1128 | EXPORT_SYMBOL(compat_ipv6_getsockopt); | 1093 | EXPORT_SYMBOL(compat_ipv6_getsockopt); |
1129 | #endif | 1094 | #endif |
1130 | 1095 | ||
1131 | int __init ipv6_packet_init(void) | ||
1132 | { | ||
1133 | dev_add_pack(&ipv6_packet_type); | ||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | void ipv6_packet_cleanup(void) | ||
1138 | { | ||
1139 | dev_remove_pack(&ipv6_packet_type); | ||
1140 | } | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index ab228d1ea114..d810cff818cf 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -126,8 +126,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | |||
126 | /* Big mc list lock for all the sockets */ | 126 | /* Big mc list lock for all the sockets */ |
127 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); | 127 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); |
128 | 128 | ||
129 | static struct socket *igmp6_socket; | ||
130 | |||
131 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); | 129 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); |
132 | 130 | ||
133 | static void igmp6_join_group(struct ifmcaddr6 *ma); | 131 | static void igmp6_join_group(struct ifmcaddr6 *ma); |
@@ -183,6 +181,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
183 | struct net_device *dev = NULL; | 181 | struct net_device *dev = NULL; |
184 | struct ipv6_mc_socklist *mc_lst; | 182 | struct ipv6_mc_socklist *mc_lst; |
185 | struct ipv6_pinfo *np = inet6_sk(sk); | 183 | struct ipv6_pinfo *np = inet6_sk(sk); |
184 | struct net *net = sock_net(sk); | ||
186 | int err; | 185 | int err; |
187 | 186 | ||
188 | if (!ipv6_addr_is_multicast(addr)) | 187 | if (!ipv6_addr_is_multicast(addr)) |
@@ -208,14 +207,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
208 | 207 | ||
209 | if (ifindex == 0) { | 208 | if (ifindex == 0) { |
210 | struct rt6_info *rt; | 209 | struct rt6_info *rt; |
211 | rt = rt6_lookup(addr, NULL, 0, 0); | 210 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
212 | if (rt) { | 211 | if (rt) { |
213 | dev = rt->rt6i_dev; | 212 | dev = rt->rt6i_dev; |
214 | dev_hold(dev); | 213 | dev_hold(dev); |
215 | dst_release(&rt->u.dst); | 214 | dst_release(&rt->u.dst); |
216 | } | 215 | } |
217 | } else | 216 | } else |
218 | dev = dev_get_by_index(&init_net, ifindex); | 217 | dev = dev_get_by_index(net, ifindex); |
219 | 218 | ||
220 | if (dev == NULL) { | 219 | if (dev == NULL) { |
221 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 220 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
@@ -256,6 +255,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
256 | { | 255 | { |
257 | struct ipv6_pinfo *np = inet6_sk(sk); | 256 | struct ipv6_pinfo *np = inet6_sk(sk); |
258 | struct ipv6_mc_socklist *mc_lst, **lnk; | 257 | struct ipv6_mc_socklist *mc_lst, **lnk; |
258 | struct net *net = sock_net(sk); | ||
259 | 259 | ||
260 | write_lock_bh(&ipv6_sk_mc_lock); | 260 | write_lock_bh(&ipv6_sk_mc_lock); |
261 | for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { | 261 | for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { |
@@ -266,7 +266,8 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
266 | *lnk = mc_lst->next; | 266 | *lnk = mc_lst->next; |
267 | write_unlock_bh(&ipv6_sk_mc_lock); | 267 | write_unlock_bh(&ipv6_sk_mc_lock); |
268 | 268 | ||
269 | if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) { | 269 | dev = dev_get_by_index(net, mc_lst->ifindex); |
270 | if (dev != NULL) { | ||
270 | struct inet6_dev *idev = in6_dev_get(dev); | 271 | struct inet6_dev *idev = in6_dev_get(dev); |
271 | 272 | ||
272 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | 273 | (void) ip6_mc_leave_src(sk, mc_lst, idev); |
@@ -286,7 +287,9 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
286 | return -EADDRNOTAVAIL; | 287 | return -EADDRNOTAVAIL; |
287 | } | 288 | } |
288 | 289 | ||
289 | static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex) | 290 | static struct inet6_dev *ip6_mc_find_dev(struct net *net, |
291 | struct in6_addr *group, | ||
292 | int ifindex) | ||
290 | { | 293 | { |
291 | struct net_device *dev = NULL; | 294 | struct net_device *dev = NULL; |
292 | struct inet6_dev *idev = NULL; | 295 | struct inet6_dev *idev = NULL; |
@@ -294,14 +297,14 @@ static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex) | |||
294 | if (ifindex == 0) { | 297 | if (ifindex == 0) { |
295 | struct rt6_info *rt; | 298 | struct rt6_info *rt; |
296 | 299 | ||
297 | rt = rt6_lookup(group, NULL, 0, 0); | 300 | rt = rt6_lookup(net, group, NULL, 0, 0); |
298 | if (rt) { | 301 | if (rt) { |
299 | dev = rt->rt6i_dev; | 302 | dev = rt->rt6i_dev; |
300 | dev_hold(dev); | 303 | dev_hold(dev); |
301 | dst_release(&rt->u.dst); | 304 | dst_release(&rt->u.dst); |
302 | } | 305 | } |
303 | } else | 306 | } else |
304 | dev = dev_get_by_index(&init_net, ifindex); | 307 | dev = dev_get_by_index(net, ifindex); |
305 | 308 | ||
306 | if (!dev) | 309 | if (!dev) |
307 | return NULL; | 310 | return NULL; |
@@ -324,6 +327,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
324 | { | 327 | { |
325 | struct ipv6_pinfo *np = inet6_sk(sk); | 328 | struct ipv6_pinfo *np = inet6_sk(sk); |
326 | struct ipv6_mc_socklist *mc_lst; | 329 | struct ipv6_mc_socklist *mc_lst; |
330 | struct net *net = sock_net(sk); | ||
327 | 331 | ||
328 | write_lock_bh(&ipv6_sk_mc_lock); | 332 | write_lock_bh(&ipv6_sk_mc_lock); |
329 | while ((mc_lst = np->ipv6_mc_list) != NULL) { | 333 | while ((mc_lst = np->ipv6_mc_list) != NULL) { |
@@ -332,7 +336,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
332 | np->ipv6_mc_list = mc_lst->next; | 336 | np->ipv6_mc_list = mc_lst->next; |
333 | write_unlock_bh(&ipv6_sk_mc_lock); | 337 | write_unlock_bh(&ipv6_sk_mc_lock); |
334 | 338 | ||
335 | dev = dev_get_by_index(&init_net, mc_lst->ifindex); | 339 | dev = dev_get_by_index(net, mc_lst->ifindex); |
336 | if (dev) { | 340 | if (dev) { |
337 | struct inet6_dev *idev = in6_dev_get(dev); | 341 | struct inet6_dev *idev = in6_dev_get(dev); |
338 | 342 | ||
@@ -361,6 +365,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
361 | struct inet6_dev *idev; | 365 | struct inet6_dev *idev; |
362 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 366 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
363 | struct ip6_sf_socklist *psl; | 367 | struct ip6_sf_socklist *psl; |
368 | struct net *net = sock_net(sk); | ||
364 | int i, j, rv; | 369 | int i, j, rv; |
365 | int leavegroup = 0; | 370 | int leavegroup = 0; |
366 | int pmclocked = 0; | 371 | int pmclocked = 0; |
@@ -376,7 +381,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
376 | if (!ipv6_addr_is_multicast(group)) | 381 | if (!ipv6_addr_is_multicast(group)) |
377 | return -EINVAL; | 382 | return -EINVAL; |
378 | 383 | ||
379 | idev = ip6_mc_find_dev(group, pgsr->gsr_interface); | 384 | idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface); |
380 | if (!idev) | 385 | if (!idev) |
381 | return -ENODEV; | 386 | return -ENODEV; |
382 | dev = idev->dev; | 387 | dev = idev->dev; |
@@ -500,6 +505,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
500 | struct inet6_dev *idev; | 505 | struct inet6_dev *idev; |
501 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 506 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
502 | struct ip6_sf_socklist *newpsl, *psl; | 507 | struct ip6_sf_socklist *newpsl, *psl; |
508 | struct net *net = sock_net(sk); | ||
503 | int leavegroup = 0; | 509 | int leavegroup = 0; |
504 | int i, err; | 510 | int i, err; |
505 | 511 | ||
@@ -511,7 +517,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
511 | gsf->gf_fmode != MCAST_EXCLUDE) | 517 | gsf->gf_fmode != MCAST_EXCLUDE) |
512 | return -EINVAL; | 518 | return -EINVAL; |
513 | 519 | ||
514 | idev = ip6_mc_find_dev(group, gsf->gf_interface); | 520 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); |
515 | 521 | ||
516 | if (!idev) | 522 | if (!idev) |
517 | return -ENODEV; | 523 | return -ENODEV; |
@@ -592,13 +598,14 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
592 | struct net_device *dev; | 598 | struct net_device *dev; |
593 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 599 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
594 | struct ip6_sf_socklist *psl; | 600 | struct ip6_sf_socklist *psl; |
601 | struct net *net = sock_net(sk); | ||
595 | 602 | ||
596 | group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; | 603 | group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; |
597 | 604 | ||
598 | if (!ipv6_addr_is_multicast(group)) | 605 | if (!ipv6_addr_is_multicast(group)) |
599 | return -EINVAL; | 606 | return -EINVAL; |
600 | 607 | ||
601 | idev = ip6_mc_find_dev(group, gsf->gf_interface); | 608 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); |
602 | 609 | ||
603 | if (!idev) | 610 | if (!idev) |
604 | return -ENODEV; | 611 | return -ENODEV; |
@@ -1393,7 +1400,8 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted) | |||
1393 | 1400 | ||
1394 | static struct sk_buff *mld_newpack(struct net_device *dev, int size) | 1401 | static struct sk_buff *mld_newpack(struct net_device *dev, int size) |
1395 | { | 1402 | { |
1396 | struct sock *sk = igmp6_socket->sk; | 1403 | struct net *net = dev_net(dev); |
1404 | struct sock *sk = net->ipv6.igmp_sk; | ||
1397 | struct sk_buff *skb; | 1405 | struct sk_buff *skb; |
1398 | struct mld2_report *pmr; | 1406 | struct mld2_report *pmr; |
1399 | struct in6_addr addr_buf; | 1407 | struct in6_addr addr_buf; |
@@ -1433,25 +1441,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1433 | return skb; | 1441 | return skb; |
1434 | } | 1442 | } |
1435 | 1443 | ||
1436 | static inline int mld_dev_queue_xmit2(struct sk_buff *skb) | ||
1437 | { | ||
1438 | struct net_device *dev = skb->dev; | ||
1439 | unsigned char ha[MAX_ADDR_LEN]; | ||
1440 | |||
1441 | ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1); | ||
1442 | if (dev_hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len) < 0) { | ||
1443 | kfree_skb(skb); | ||
1444 | return -EINVAL; | ||
1445 | } | ||
1446 | return dev_queue_xmit(skb); | ||
1447 | } | ||
1448 | |||
1449 | static inline int mld_dev_queue_xmit(struct sk_buff *skb) | ||
1450 | { | ||
1451 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | ||
1452 | mld_dev_queue_xmit2); | ||
1453 | } | ||
1454 | |||
1455 | static void mld_sendpack(struct sk_buff *skb) | 1444 | static void mld_sendpack(struct sk_buff *skb) |
1456 | { | 1445 | { |
1457 | struct ipv6hdr *pip6 = ipv6_hdr(skb); | 1446 | struct ipv6hdr *pip6 = ipv6_hdr(skb); |
@@ -1459,7 +1448,9 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1459 | (struct mld2_report *)skb_transport_header(skb); | 1448 | (struct mld2_report *)skb_transport_header(skb); |
1460 | int payload_len, mldlen; | 1449 | int payload_len, mldlen; |
1461 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1450 | struct inet6_dev *idev = in6_dev_get(skb->dev); |
1451 | struct net *net = dev_net(skb->dev); | ||
1462 | int err; | 1452 | int err; |
1453 | struct flowi fl; | ||
1463 | 1454 | ||
1464 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); | 1455 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
1465 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); | 1456 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); |
@@ -1469,8 +1460,25 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1469 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1460 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
1470 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), | 1461 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), |
1471 | mldlen, 0)); | 1462 | mldlen, 0)); |
1463 | |||
1464 | skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | ||
1465 | |||
1466 | if (!skb->dst) { | ||
1467 | err = -ENOMEM; | ||
1468 | goto err_out; | ||
1469 | } | ||
1470 | |||
1471 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT, | ||
1472 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | ||
1473 | skb->dev->ifindex); | ||
1474 | |||
1475 | err = xfrm_lookup(&skb->dst, &fl, NULL, 0); | ||
1476 | if (err) | ||
1477 | goto err_out; | ||
1478 | |||
1472 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1479 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1473 | mld_dev_queue_xmit); | 1480 | dst_output); |
1481 | out: | ||
1474 | if (!err) { | 1482 | if (!err) { |
1475 | ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); | 1483 | ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); |
1476 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); | 1484 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); |
@@ -1480,6 +1488,11 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1480 | 1488 | ||
1481 | if (likely(idev != NULL)) | 1489 | if (likely(idev != NULL)) |
1482 | in6_dev_put(idev); | 1490 | in6_dev_put(idev); |
1491 | return; | ||
1492 | |||
1493 | err_out: | ||
1494 | kfree_skb(skb); | ||
1495 | goto out; | ||
1483 | } | 1496 | } |
1484 | 1497 | ||
1485 | static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) | 1498 | static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) |
@@ -1749,7 +1762,8 @@ static void mld_send_cr(struct inet6_dev *idev) | |||
1749 | 1762 | ||
1750 | static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | 1763 | static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) |
1751 | { | 1764 | { |
1752 | struct sock *sk = igmp6_socket->sk; | 1765 | struct net *net = dev_net(dev); |
1766 | struct sock *sk = net->ipv6.igmp_sk; | ||
1753 | struct inet6_dev *idev; | 1767 | struct inet6_dev *idev; |
1754 | struct sk_buff *skb; | 1768 | struct sk_buff *skb; |
1755 | struct icmp6hdr *hdr; | 1769 | struct icmp6hdr *hdr; |
@@ -1761,6 +1775,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1761 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1775 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1762 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1776 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1763 | IPV6_TLV_PADN, 0 }; | 1777 | IPV6_TLV_PADN, 0 }; |
1778 | struct flowi fl; | ||
1764 | 1779 | ||
1765 | rcu_read_lock(); | 1780 | rcu_read_lock(); |
1766 | IP6_INC_STATS(__in6_dev_get(dev), | 1781 | IP6_INC_STATS(__in6_dev_get(dev), |
@@ -1813,8 +1828,23 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1813 | 1828 | ||
1814 | idev = in6_dev_get(skb->dev); | 1829 | idev = in6_dev_get(skb->dev); |
1815 | 1830 | ||
1831 | skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | ||
1832 | if (!skb->dst) { | ||
1833 | err = -ENOMEM; | ||
1834 | goto err_out; | ||
1835 | } | ||
1836 | |||
1837 | icmpv6_flow_init(sk, &fl, type, | ||
1838 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | ||
1839 | skb->dev->ifindex); | ||
1840 | |||
1841 | err = xfrm_lookup(&skb->dst, &fl, NULL, 0); | ||
1842 | if (err) | ||
1843 | goto err_out; | ||
1844 | |||
1816 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1845 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1817 | mld_dev_queue_xmit); | 1846 | dst_output); |
1847 | out: | ||
1818 | if (!err) { | 1848 | if (!err) { |
1819 | ICMP6MSGOUT_INC_STATS(idev, type); | 1849 | ICMP6MSGOUT_INC_STATS(idev, type); |
1820 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); | 1850 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); |
@@ -1825,6 +1855,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1825 | if (likely(idev != NULL)) | 1855 | if (likely(idev != NULL)) |
1826 | in6_dev_put(idev); | 1856 | in6_dev_put(idev); |
1827 | return; | 1857 | return; |
1858 | |||
1859 | err_out: | ||
1860 | kfree_skb(skb); | ||
1861 | goto out; | ||
1828 | } | 1862 | } |
1829 | 1863 | ||
1830 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | 1864 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, |
@@ -2310,6 +2344,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev) | |||
2310 | 2344 | ||
2311 | #ifdef CONFIG_PROC_FS | 2345 | #ifdef CONFIG_PROC_FS |
2312 | struct igmp6_mc_iter_state { | 2346 | struct igmp6_mc_iter_state { |
2347 | struct seq_net_private p; | ||
2313 | struct net_device *dev; | 2348 | struct net_device *dev; |
2314 | struct inet6_dev *idev; | 2349 | struct inet6_dev *idev; |
2315 | }; | 2350 | }; |
@@ -2320,9 +2355,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq) | |||
2320 | { | 2355 | { |
2321 | struct ifmcaddr6 *im = NULL; | 2356 | struct ifmcaddr6 *im = NULL; |
2322 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); | 2357 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); |
2358 | struct net *net = seq_file_net(seq); | ||
2323 | 2359 | ||
2324 | state->idev = NULL; | 2360 | state->idev = NULL; |
2325 | for_each_netdev(&init_net, state->dev) { | 2361 | for_each_netdev(net, state->dev) { |
2326 | struct inet6_dev *idev; | 2362 | struct inet6_dev *idev; |
2327 | idev = in6_dev_get(state->dev); | 2363 | idev = in6_dev_get(state->dev); |
2328 | if (!idev) | 2364 | if (!idev) |
@@ -2424,8 +2460,8 @@ static const struct seq_operations igmp6_mc_seq_ops = { | |||
2424 | 2460 | ||
2425 | static int igmp6_mc_seq_open(struct inode *inode, struct file *file) | 2461 | static int igmp6_mc_seq_open(struct inode *inode, struct file *file) |
2426 | { | 2462 | { |
2427 | return seq_open_private(file, &igmp6_mc_seq_ops, | 2463 | return seq_open_net(inode, file, &igmp6_mc_seq_ops, |
2428 | sizeof(struct igmp6_mc_iter_state)); | 2464 | sizeof(struct igmp6_mc_iter_state)); |
2429 | } | 2465 | } |
2430 | 2466 | ||
2431 | static const struct file_operations igmp6_mc_seq_fops = { | 2467 | static const struct file_operations igmp6_mc_seq_fops = { |
@@ -2433,10 +2469,11 @@ static const struct file_operations igmp6_mc_seq_fops = { | |||
2433 | .open = igmp6_mc_seq_open, | 2469 | .open = igmp6_mc_seq_open, |
2434 | .read = seq_read, | 2470 | .read = seq_read, |
2435 | .llseek = seq_lseek, | 2471 | .llseek = seq_lseek, |
2436 | .release = seq_release_private, | 2472 | .release = seq_release_net, |
2437 | }; | 2473 | }; |
2438 | 2474 | ||
2439 | struct igmp6_mcf_iter_state { | 2475 | struct igmp6_mcf_iter_state { |
2476 | struct seq_net_private p; | ||
2440 | struct net_device *dev; | 2477 | struct net_device *dev; |
2441 | struct inet6_dev *idev; | 2478 | struct inet6_dev *idev; |
2442 | struct ifmcaddr6 *im; | 2479 | struct ifmcaddr6 *im; |
@@ -2449,10 +2486,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq) | |||
2449 | struct ip6_sf_list *psf = NULL; | 2486 | struct ip6_sf_list *psf = NULL; |
2450 | struct ifmcaddr6 *im = NULL; | 2487 | struct ifmcaddr6 *im = NULL; |
2451 | struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); | 2488 | struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); |
2489 | struct net *net = seq_file_net(seq); | ||
2452 | 2490 | ||
2453 | state->idev = NULL; | 2491 | state->idev = NULL; |
2454 | state->im = NULL; | 2492 | state->im = NULL; |
2455 | for_each_netdev(&init_net, state->dev) { | 2493 | for_each_netdev(net, state->dev) { |
2456 | struct inet6_dev *idev; | 2494 | struct inet6_dev *idev; |
2457 | idev = in6_dev_get(state->dev); | 2495 | idev = in6_dev_get(state->dev); |
2458 | if (unlikely(idev == NULL)) | 2496 | if (unlikely(idev == NULL)) |
@@ -2584,8 +2622,8 @@ static const struct seq_operations igmp6_mcf_seq_ops = { | |||
2584 | 2622 | ||
2585 | static int igmp6_mcf_seq_open(struct inode *inode, struct file *file) | 2623 | static int igmp6_mcf_seq_open(struct inode *inode, struct file *file) |
2586 | { | 2624 | { |
2587 | return seq_open_private(file, &igmp6_mcf_seq_ops, | 2625 | return seq_open_net(inode, file, &igmp6_mcf_seq_ops, |
2588 | sizeof(struct igmp6_mcf_iter_state)); | 2626 | sizeof(struct igmp6_mcf_iter_state)); |
2589 | } | 2627 | } |
2590 | 2628 | ||
2591 | static const struct file_operations igmp6_mcf_seq_fops = { | 2629 | static const struct file_operations igmp6_mcf_seq_fops = { |
@@ -2593,47 +2631,96 @@ static const struct file_operations igmp6_mcf_seq_fops = { | |||
2593 | .open = igmp6_mcf_seq_open, | 2631 | .open = igmp6_mcf_seq_open, |
2594 | .read = seq_read, | 2632 | .read = seq_read, |
2595 | .llseek = seq_lseek, | 2633 | .llseek = seq_lseek, |
2596 | .release = seq_release_private, | 2634 | .release = seq_release_net, |
2597 | }; | 2635 | }; |
2636 | |||
2637 | static int igmp6_proc_init(struct net *net) | ||
2638 | { | ||
2639 | int err; | ||
2640 | |||
2641 | err = -ENOMEM; | ||
2642 | if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops)) | ||
2643 | goto out; | ||
2644 | if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO, | ||
2645 | &igmp6_mcf_seq_fops)) | ||
2646 | goto out_proc_net_igmp6; | ||
2647 | |||
2648 | err = 0; | ||
2649 | out: | ||
2650 | return err; | ||
2651 | |||
2652 | out_proc_net_igmp6: | ||
2653 | proc_net_remove(net, "igmp6"); | ||
2654 | goto out; | ||
2655 | } | ||
2656 | |||
2657 | static void igmp6_proc_exit(struct net *net) | ||
2658 | { | ||
2659 | proc_net_remove(net, "mcfilter6"); | ||
2660 | proc_net_remove(net, "igmp6"); | ||
2661 | } | ||
2662 | #else | ||
2663 | static int igmp6_proc_init(struct net *net) | ||
2664 | { | ||
2665 | return 0; | ||
2666 | } | ||
2667 | static void igmp6_proc_exit(struct net *net) | ||
2668 | { | ||
2669 | ; | ||
2670 | } | ||
2598 | #endif | 2671 | #endif |
2599 | 2672 | ||
2600 | int __init igmp6_init(struct net_proto_family *ops) | 2673 | static int igmp6_net_init(struct net *net) |
2601 | { | 2674 | { |
2602 | struct ipv6_pinfo *np; | 2675 | struct ipv6_pinfo *np; |
2676 | struct socket *sock; | ||
2603 | struct sock *sk; | 2677 | struct sock *sk; |
2604 | int err; | 2678 | int err; |
2605 | 2679 | ||
2606 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket); | 2680 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &sock); |
2607 | if (err < 0) { | 2681 | if (err < 0) { |
2608 | printk(KERN_ERR | 2682 | printk(KERN_ERR |
2609 | "Failed to initialize the IGMP6 control socket (err %d).\n", | 2683 | "Failed to initialize the IGMP6 control socket (err %d).\n", |
2610 | err); | 2684 | err); |
2611 | igmp6_socket = NULL; /* For safety. */ | 2685 | goto out; |
2612 | return err; | ||
2613 | } | 2686 | } |
2614 | 2687 | ||
2615 | sk = igmp6_socket->sk; | 2688 | net->ipv6.igmp_sk = sk = sock->sk; |
2689 | sk_change_net(sk, net); | ||
2616 | sk->sk_allocation = GFP_ATOMIC; | 2690 | sk->sk_allocation = GFP_ATOMIC; |
2617 | sk->sk_prot->unhash(sk); | 2691 | sk->sk_prot->unhash(sk); |
2618 | 2692 | ||
2619 | np = inet6_sk(sk); | 2693 | np = inet6_sk(sk); |
2620 | np->hop_limit = 1; | 2694 | np->hop_limit = 1; |
2621 | 2695 | ||
2622 | #ifdef CONFIG_PROC_FS | 2696 | err = igmp6_proc_init(net); |
2623 | proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops); | 2697 | if (err) |
2624 | proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops); | 2698 | goto out_sock_create; |
2625 | #endif | 2699 | out: |
2700 | return err; | ||
2626 | 2701 | ||
2627 | return 0; | 2702 | out_sock_create: |
2703 | sk_release_kernel(net->ipv6.igmp_sk); | ||
2704 | goto out; | ||
2628 | } | 2705 | } |
2629 | 2706 | ||
2630 | void igmp6_cleanup(void) | 2707 | static void igmp6_net_exit(struct net *net) |
2631 | { | 2708 | { |
2632 | sock_release(igmp6_socket); | 2709 | sk_release_kernel(net->ipv6.igmp_sk); |
2633 | igmp6_socket = NULL; /* for safety */ | 2710 | igmp6_proc_exit(net); |
2711 | } | ||
2634 | 2712 | ||
2635 | #ifdef CONFIG_PROC_FS | 2713 | static struct pernet_operations igmp6_net_ops = { |
2636 | proc_net_remove(&init_net, "mcfilter6"); | 2714 | .init = igmp6_net_init, |
2637 | proc_net_remove(&init_net, "igmp6"); | 2715 | .exit = igmp6_net_exit, |
2638 | #endif | 2716 | }; |
2717 | |||
2718 | int __init igmp6_init(void) | ||
2719 | { | ||
2720 | return register_pernet_subsys(&igmp6_net_ops); | ||
2721 | } | ||
2722 | |||
2723 | void igmp6_cleanup(void) | ||
2724 | { | ||
2725 | unregister_pernet_subsys(&igmp6_net_ops); | ||
2639 | } | 2726 | } |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index cd8a5bda13cd..42403c626c27 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -304,13 +304,13 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
304 | static int mip6_destopt_init_state(struct xfrm_state *x) | 304 | static int mip6_destopt_init_state(struct xfrm_state *x) |
305 | { | 305 | { |
306 | if (x->id.spi) { | 306 | if (x->id.spi) { |
307 | printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__, | 307 | printk(KERN_INFO "%s: spi is not 0: %u\n", __func__, |
308 | x->id.spi); | 308 | x->id.spi); |
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | } | 310 | } |
311 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { | 311 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { |
312 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", | 312 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", |
313 | __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); | 313 | __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); |
314 | return -EINVAL; | 314 | return -EINVAL; |
315 | } | 315 | } |
316 | 316 | ||
@@ -439,13 +439,13 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
439 | static int mip6_rthdr_init_state(struct xfrm_state *x) | 439 | static int mip6_rthdr_init_state(struct xfrm_state *x) |
440 | { | 440 | { |
441 | if (x->id.spi) { | 441 | if (x->id.spi) { |
442 | printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__, | 442 | printk(KERN_INFO "%s: spi is not 0: %u\n", __func__, |
443 | x->id.spi); | 443 | x->id.spi); |
444 | return -EINVAL; | 444 | return -EINVAL; |
445 | } | 445 | } |
446 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { | 446 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { |
447 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", | 447 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", |
448 | __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); | 448 | __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); |
449 | return -EINVAL; | 449 | return -EINVAL; |
450 | } | 450 | } |
451 | 451 | ||
@@ -480,15 +480,15 @@ static int __init mip6_init(void) | |||
480 | printk(KERN_INFO "Mobile IPv6\n"); | 480 | printk(KERN_INFO "Mobile IPv6\n"); |
481 | 481 | ||
482 | if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) { | 482 | if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) { |
483 | printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__); | 483 | printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __func__); |
484 | goto mip6_destopt_xfrm_fail; | 484 | goto mip6_destopt_xfrm_fail; |
485 | } | 485 | } |
486 | if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) { | 486 | if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) { |
487 | printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); | 487 | printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __func__); |
488 | goto mip6_rthdr_xfrm_fail; | 488 | goto mip6_rthdr_xfrm_fail; |
489 | } | 489 | } |
490 | if (rawv6_mh_filter_register(mip6_mh_filter) < 0) { | 490 | if (rawv6_mh_filter_register(mip6_mh_filter) < 0) { |
491 | printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__); | 491 | printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __func__); |
492 | goto mip6_rawv6_mh_fail; | 492 | goto mip6_rawv6_mh_fail; |
493 | } | 493 | } |
494 | 494 | ||
@@ -506,11 +506,11 @@ static int __init mip6_init(void) | |||
506 | static void __exit mip6_fini(void) | 506 | static void __exit mip6_fini(void) |
507 | { | 507 | { |
508 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) | 508 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) |
509 | printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__); | 509 | printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __func__); |
510 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) | 510 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) |
511 | printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); | 511 | printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __func__); |
512 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) | 512 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) |
513 | printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); | 513 | printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __func__); |
514 | } | 514 | } |
515 | 515 | ||
516 | module_init(mip6_init); | 516 | module_init(mip6_init); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 452a2ac4eec8..e77b74edfd63 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -89,8 +89,6 @@ | |||
89 | #include <linux/netfilter.h> | 89 | #include <linux/netfilter.h> |
90 | #include <linux/netfilter_ipv6.h> | 90 | #include <linux/netfilter_ipv6.h> |
91 | 91 | ||
92 | static struct socket *ndisc_socket; | ||
93 | |||
94 | static u32 ndisc_hash(const void *pkey, const struct net_device *dev); | 92 | static u32 ndisc_hash(const void *pkey, const struct net_device *dev); |
95 | static int ndisc_constructor(struct neighbour *neigh); | 93 | static int ndisc_constructor(struct neighbour *neigh); |
96 | static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); | 94 | static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); |
@@ -270,7 +268,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, | |||
270 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { | 268 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { |
271 | ND_PRINTK2(KERN_WARNING | 269 | ND_PRINTK2(KERN_WARNING |
272 | "%s(): duplicated ND6 option found: type=%d\n", | 270 | "%s(): duplicated ND6 option found: type=%d\n", |
273 | __FUNCTION__, | 271 | __func__, |
274 | nd_opt->nd_opt_type); | 272 | nd_opt->nd_opt_type); |
275 | } else { | 273 | } else { |
276 | ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; | 274 | ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; |
@@ -301,7 +299,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, | |||
301 | */ | 299 | */ |
302 | ND_PRINTK2(KERN_NOTICE | 300 | ND_PRINTK2(KERN_NOTICE |
303 | "%s(): ignored unsupported option; type=%d, len=%d\n", | 301 | "%s(): ignored unsupported option; type=%d, len=%d\n", |
304 | __FUNCTION__, | 302 | __func__, |
305 | nd_opt->nd_opt_type, nd_opt->nd_opt_len); | 303 | nd_opt->nd_opt_type, nd_opt->nd_opt_len); |
306 | } | 304 | } |
307 | } | 305 | } |
@@ -441,21 +439,6 @@ static void pndisc_destructor(struct pneigh_entry *n) | |||
441 | /* | 439 | /* |
442 | * Send a Neighbour Advertisement | 440 | * Send a Neighbour Advertisement |
443 | */ | 441 | */ |
444 | |||
445 | static inline void ndisc_flow_init(struct flowi *fl, u8 type, | ||
446 | struct in6_addr *saddr, struct in6_addr *daddr, | ||
447 | int oif) | ||
448 | { | ||
449 | memset(fl, 0, sizeof(*fl)); | ||
450 | ipv6_addr_copy(&fl->fl6_src, saddr); | ||
451 | ipv6_addr_copy(&fl->fl6_dst, daddr); | ||
452 | fl->proto = IPPROTO_ICMPV6; | ||
453 | fl->fl_icmp_type = type; | ||
454 | fl->fl_icmp_code = 0; | ||
455 | fl->oif = oif; | ||
456 | security_sk_classify_flow(ndisc_socket->sk, fl); | ||
457 | } | ||
458 | |||
459 | static void __ndisc_send(struct net_device *dev, | 442 | static void __ndisc_send(struct net_device *dev, |
460 | struct neighbour *neigh, | 443 | struct neighbour *neigh, |
461 | struct in6_addr *daddr, struct in6_addr *saddr, | 444 | struct in6_addr *daddr, struct in6_addr *saddr, |
@@ -464,7 +447,8 @@ static void __ndisc_send(struct net_device *dev, | |||
464 | { | 447 | { |
465 | struct flowi fl; | 448 | struct flowi fl; |
466 | struct dst_entry *dst; | 449 | struct dst_entry *dst; |
467 | struct sock *sk = ndisc_socket->sk; | 450 | struct net *net = dev_net(dev); |
451 | struct sock *sk = net->ipv6.ndisc_sk; | ||
468 | struct sk_buff *skb; | 452 | struct sk_buff *skb; |
469 | struct icmp6hdr *hdr; | 453 | struct icmp6hdr *hdr; |
470 | struct inet6_dev *idev; | 454 | struct inet6_dev *idev; |
@@ -474,10 +458,9 @@ static void __ndisc_send(struct net_device *dev, | |||
474 | 458 | ||
475 | type = icmp6h->icmp6_type; | 459 | type = icmp6h->icmp6_type; |
476 | 460 | ||
477 | ndisc_flow_init(&fl, type, saddr, daddr, | 461 | icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex); |
478 | dev->ifindex); | ||
479 | 462 | ||
480 | dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); | 463 | dst = icmp6_dst_alloc(dev, neigh, daddr); |
481 | if (!dst) | 464 | if (!dst) |
482 | return; | 465 | return; |
483 | 466 | ||
@@ -499,7 +482,7 @@ static void __ndisc_send(struct net_device *dev, | |||
499 | if (!skb) { | 482 | if (!skb) { |
500 | ND_PRINTK0(KERN_ERR | 483 | ND_PRINTK0(KERN_ERR |
501 | "ICMPv6 ND: %s() failed to allocate an skb.\n", | 484 | "ICMPv6 ND: %s() failed to allocate an skb.\n", |
502 | __FUNCTION__); | 485 | __func__); |
503 | dst_release(dst); | 486 | dst_release(dst); |
504 | return; | 487 | return; |
505 | } | 488 | } |
@@ -556,14 +539,16 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
556 | }; | 539 | }; |
557 | 540 | ||
558 | /* for anycast or proxy, solicited_addr != src_addr */ | 541 | /* for anycast or proxy, solicited_addr != src_addr */ |
559 | ifp = ipv6_get_ifaddr(&init_net, solicited_addr, dev, 1); | 542 | ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1); |
560 | if (ifp) { | 543 | if (ifp) { |
561 | src_addr = solicited_addr; | 544 | src_addr = solicited_addr; |
562 | if (ifp->flags & IFA_F_OPTIMISTIC) | 545 | if (ifp->flags & IFA_F_OPTIMISTIC) |
563 | override = 0; | 546 | override = 0; |
564 | in6_ifa_put(ifp); | 547 | in6_ifa_put(ifp); |
565 | } else { | 548 | } else { |
566 | if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) | 549 | if (ipv6_dev_get_saddr(dev, daddr, |
550 | inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs, | ||
551 | &tmpaddr)) | ||
567 | return; | 552 | return; |
568 | src_addr = &tmpaddr; | 553 | src_addr = &tmpaddr; |
569 | } | 554 | } |
@@ -616,7 +601,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
616 | * suppress the inclusion of the sllao. | 601 | * suppress the inclusion of the sllao. |
617 | */ | 602 | */ |
618 | if (send_sllao) { | 603 | if (send_sllao) { |
619 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr, | 604 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr, |
620 | dev, 1); | 605 | dev, 1); |
621 | if (ifp) { | 606 | if (ifp) { |
622 | if (ifp->flags & IFA_F_OPTIMISTIC) { | 607 | if (ifp->flags & IFA_F_OPTIMISTIC) { |
@@ -654,7 +639,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
654 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; | 639 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; |
655 | int probes = atomic_read(&neigh->probes); | 640 | int probes = atomic_read(&neigh->probes); |
656 | 641 | ||
657 | if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1)) | 642 | if (skb && ipv6_chk_addr(dev_net(dev), &ipv6_hdr(skb)->saddr, dev, 1)) |
658 | saddr = &ipv6_hdr(skb)->saddr; | 643 | saddr = &ipv6_hdr(skb)->saddr; |
659 | 644 | ||
660 | if ((probes -= neigh->parms->ucast_probes) < 0) { | 645 | if ((probes -= neigh->parms->ucast_probes) < 0) { |
@@ -662,7 +647,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
662 | ND_PRINTK1(KERN_DEBUG | 647 | ND_PRINTK1(KERN_DEBUG |
663 | "%s(): trying to ucast probe in NUD_INVALID: " | 648 | "%s(): trying to ucast probe in NUD_INVALID: " |
664 | NIP6_FMT "\n", | 649 | NIP6_FMT "\n", |
665 | __FUNCTION__, | 650 | __func__, |
666 | NIP6(*target)); | 651 | NIP6(*target)); |
667 | } | 652 | } |
668 | ndisc_send_ns(dev, neigh, target, target, saddr); | 653 | ndisc_send_ns(dev, neigh, target, target, saddr); |
@@ -682,7 +667,7 @@ static struct pneigh_entry *pndisc_check_router(struct net_device *dev, | |||
682 | struct pneigh_entry *n; | 667 | struct pneigh_entry *n; |
683 | 668 | ||
684 | read_lock_bh(&nd_tbl.lock); | 669 | read_lock_bh(&nd_tbl.lock); |
685 | n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev); | 670 | n = __pneigh_lookup(&nd_tbl, dev_net(dev), addr, dev); |
686 | if (n != NULL) | 671 | if (n != NULL) |
687 | *is_router = (n->flags & NTF_ROUTER); | 672 | *is_router = (n->flags & NTF_ROUTER); |
688 | read_unlock_bh(&nd_tbl.lock); | 673 | read_unlock_bh(&nd_tbl.lock); |
@@ -756,7 +741,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
756 | 741 | ||
757 | inc = ipv6_addr_is_multicast(daddr); | 742 | inc = ipv6_addr_is_multicast(daddr); |
758 | 743 | ||
759 | if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) { | 744 | ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); |
745 | if (ifp) { | ||
760 | 746 | ||
761 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { | 747 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { |
762 | if (dad) { | 748 | if (dad) { |
@@ -801,7 +787,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
801 | return; | 787 | return; |
802 | } | 788 | } |
803 | 789 | ||
804 | if (ipv6_chk_acast_addr(dev, &msg->target) || | 790 | if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) || |
805 | (idev->cnf.forwarding && | 791 | (idev->cnf.forwarding && |
806 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && | 792 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && |
807 | (pneigh = pndisc_check_router(dev, &msg->target, | 793 | (pneigh = pndisc_check_router(dev, &msg->target, |
@@ -914,7 +900,8 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
914 | return; | 900 | return; |
915 | } | 901 | } |
916 | } | 902 | } |
917 | if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) { | 903 | ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); |
904 | if (ifp) { | ||
918 | if (ifp->flags & IFA_F_TENTATIVE) { | 905 | if (ifp->flags & IFA_F_TENTATIVE) { |
919 | addrconf_dad_failure(ifp); | 906 | addrconf_dad_failure(ifp); |
920 | return; | 907 | return; |
@@ -945,7 +932,7 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
945 | */ | 932 | */ |
946 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && | 933 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && |
947 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && | 934 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && |
948 | pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) { | 935 | pneigh_lookup(&nd_tbl, dev_net(dev), &msg->target, dev, 0)) { |
949 | /* XXX: idev->cnf.prixy_ndp */ | 936 | /* XXX: idev->cnf.prixy_ndp */ |
950 | goto out; | 937 | goto out; |
951 | } | 938 | } |
@@ -1035,6 +1022,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1035 | struct sk_buff *skb; | 1022 | struct sk_buff *skb; |
1036 | struct nlmsghdr *nlh; | 1023 | struct nlmsghdr *nlh; |
1037 | struct nduseroptmsg *ndmsg; | 1024 | struct nduseroptmsg *ndmsg; |
1025 | struct net *net = dev_net(ra->dev); | ||
1038 | int err; | 1026 | int err; |
1039 | int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) | 1027 | int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) |
1040 | + (opt->nd_opt_len << 3)); | 1028 | + (opt->nd_opt_len << 3)); |
@@ -1064,7 +1052,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1064 | &ipv6_hdr(ra)->saddr); | 1052 | &ipv6_hdr(ra)->saddr); |
1065 | nlmsg_end(skb, nlh); | 1053 | nlmsg_end(skb, nlh); |
1066 | 1054 | ||
1067 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL, | 1055 | err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, |
1068 | GFP_ATOMIC); | 1056 | GFP_ATOMIC); |
1069 | if (err < 0) | 1057 | if (err < 0) |
1070 | goto errout; | 1058 | goto errout; |
@@ -1075,7 +1063,7 @@ nla_put_failure: | |||
1075 | nlmsg_free(skb); | 1063 | nlmsg_free(skb); |
1076 | err = -EMSGSIZE; | 1064 | err = -EMSGSIZE; |
1077 | errout: | 1065 | errout: |
1078 | rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err); | 1066 | rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err); |
1079 | } | 1067 | } |
1080 | 1068 | ||
1081 | static void ndisc_router_discovery(struct sk_buff *skb) | 1069 | static void ndisc_router_discovery(struct sk_buff *skb) |
@@ -1178,7 +1166,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1178 | if (rt == NULL) { | 1166 | if (rt == NULL) { |
1179 | ND_PRINTK0(KERN_ERR | 1167 | ND_PRINTK0(KERN_ERR |
1180 | "ICMPv6 RA: %s() failed to add default route.\n", | 1168 | "ICMPv6 RA: %s() failed to add default route.\n", |
1181 | __FUNCTION__); | 1169 | __func__); |
1182 | in6_dev_put(in6_dev); | 1170 | in6_dev_put(in6_dev); |
1183 | return; | 1171 | return; |
1184 | } | 1172 | } |
@@ -1187,7 +1175,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1187 | if (neigh == NULL) { | 1175 | if (neigh == NULL) { |
1188 | ND_PRINTK0(KERN_ERR | 1176 | ND_PRINTK0(KERN_ERR |
1189 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1177 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
1190 | __FUNCTION__); | 1178 | __func__); |
1191 | dst_release(&rt->u.dst); | 1179 | dst_release(&rt->u.dst); |
1192 | in6_dev_put(in6_dev); | 1180 | in6_dev_put(in6_dev); |
1193 | return; | 1181 | return; |
@@ -1420,13 +1408,14 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1420 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | 1408 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, |
1421 | struct in6_addr *target) | 1409 | struct in6_addr *target) |
1422 | { | 1410 | { |
1423 | struct sock *sk = ndisc_socket->sk; | 1411 | struct net_device *dev = skb->dev; |
1412 | struct net *net = dev_net(dev); | ||
1413 | struct sock *sk = net->ipv6.ndisc_sk; | ||
1424 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); | 1414 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); |
1425 | struct sk_buff *buff; | 1415 | struct sk_buff *buff; |
1426 | struct icmp6hdr *icmph; | 1416 | struct icmp6hdr *icmph; |
1427 | struct in6_addr saddr_buf; | 1417 | struct in6_addr saddr_buf; |
1428 | struct in6_addr *addrp; | 1418 | struct in6_addr *addrp; |
1429 | struct net_device *dev; | ||
1430 | struct rt6_info *rt; | 1419 | struct rt6_info *rt; |
1431 | struct dst_entry *dst; | 1420 | struct dst_entry *dst; |
1432 | struct inet6_dev *idev; | 1421 | struct inet6_dev *idev; |
@@ -1436,8 +1425,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1436 | int err; | 1425 | int err; |
1437 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; | 1426 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; |
1438 | 1427 | ||
1439 | dev = skb->dev; | ||
1440 | |||
1441 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { | 1428 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { |
1442 | ND_PRINTK2(KERN_WARNING | 1429 | ND_PRINTK2(KERN_WARNING |
1443 | "ICMPv6 Redirect: no link-local address on %s\n", | 1430 | "ICMPv6 Redirect: no link-local address on %s\n", |
@@ -1452,10 +1439,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1452 | return; | 1439 | return; |
1453 | } | 1440 | } |
1454 | 1441 | ||
1455 | ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1442 | icmpv6_flow_init(sk, &fl, NDISC_REDIRECT, |
1456 | dev->ifindex); | 1443 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); |
1457 | 1444 | ||
1458 | dst = ip6_route_output(NULL, &fl); | 1445 | dst = ip6_route_output(net, NULL, &fl); |
1459 | if (dst == NULL) | 1446 | if (dst == NULL) |
1460 | return; | 1447 | return; |
1461 | 1448 | ||
@@ -1499,12 +1486,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1499 | if (buff == NULL) { | 1486 | if (buff == NULL) { |
1500 | ND_PRINTK0(KERN_ERR | 1487 | ND_PRINTK0(KERN_ERR |
1501 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", | 1488 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", |
1502 | __FUNCTION__); | 1489 | __func__); |
1503 | dst_release(dst); | 1490 | dst_release(dst); |
1504 | return; | 1491 | return; |
1505 | } | 1492 | } |
1506 | 1493 | ||
1507 | |||
1508 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1494 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); |
1509 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1495 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, |
1510 | IPPROTO_ICMPV6, len); | 1496 | IPPROTO_ICMPV6, len); |
@@ -1625,18 +1611,16 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1625 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1611 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1626 | { | 1612 | { |
1627 | struct net_device *dev = ptr; | 1613 | struct net_device *dev = ptr; |
1628 | 1614 | struct net *net = dev_net(dev); | |
1629 | if (dev->nd_net != &init_net) | ||
1630 | return NOTIFY_DONE; | ||
1631 | 1615 | ||
1632 | switch (event) { | 1616 | switch (event) { |
1633 | case NETDEV_CHANGEADDR: | 1617 | case NETDEV_CHANGEADDR: |
1634 | neigh_changeaddr(&nd_tbl, dev); | 1618 | neigh_changeaddr(&nd_tbl, dev); |
1635 | fib6_run_gc(~0UL); | 1619 | fib6_run_gc(~0UL, net); |
1636 | break; | 1620 | break; |
1637 | case NETDEV_DOWN: | 1621 | case NETDEV_DOWN: |
1638 | neigh_ifdown(&nd_tbl, dev); | 1622 | neigh_ifdown(&nd_tbl, dev); |
1639 | fib6_run_gc(~0UL); | 1623 | fib6_run_gc(~0UL, net); |
1640 | break; | 1624 | break; |
1641 | default: | 1625 | default: |
1642 | break; | 1626 | break; |
@@ -1745,22 +1729,24 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, | |||
1745 | 1729 | ||
1746 | #endif | 1730 | #endif |
1747 | 1731 | ||
1748 | int __init ndisc_init(struct net_proto_family *ops) | 1732 | static int ndisc_net_init(struct net *net) |
1749 | { | 1733 | { |
1734 | struct socket *sock; | ||
1750 | struct ipv6_pinfo *np; | 1735 | struct ipv6_pinfo *np; |
1751 | struct sock *sk; | 1736 | struct sock *sk; |
1752 | int err; | 1737 | int err; |
1753 | 1738 | ||
1754 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket); | 1739 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &sock); |
1755 | if (err < 0) { | 1740 | if (err < 0) { |
1756 | ND_PRINTK0(KERN_ERR | 1741 | ND_PRINTK0(KERN_ERR |
1757 | "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", | 1742 | "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", |
1758 | err); | 1743 | err); |
1759 | ndisc_socket = NULL; /* For safety. */ | ||
1760 | return err; | 1744 | return err; |
1761 | } | 1745 | } |
1762 | 1746 | ||
1763 | sk = ndisc_socket->sk; | 1747 | net->ipv6.ndisc_sk = sk = sock->sk; |
1748 | sk_change_net(sk, net); | ||
1749 | |||
1764 | np = inet6_sk(sk); | 1750 | np = inet6_sk(sk); |
1765 | sk->sk_allocation = GFP_ATOMIC; | 1751 | sk->sk_allocation = GFP_ATOMIC; |
1766 | np->hop_limit = 255; | 1752 | np->hop_limit = 255; |
@@ -1768,21 +1754,52 @@ int __init ndisc_init(struct net_proto_family *ops) | |||
1768 | np->mc_loop = 0; | 1754 | np->mc_loop = 0; |
1769 | sk->sk_prot->unhash(sk); | 1755 | sk->sk_prot->unhash(sk); |
1770 | 1756 | ||
1757 | return 0; | ||
1758 | } | ||
1759 | |||
1760 | static void ndisc_net_exit(struct net *net) | ||
1761 | { | ||
1762 | sk_release_kernel(net->ipv6.ndisc_sk); | ||
1763 | } | ||
1764 | |||
1765 | static struct pernet_operations ndisc_net_ops = { | ||
1766 | .init = ndisc_net_init, | ||
1767 | .exit = ndisc_net_exit, | ||
1768 | }; | ||
1769 | |||
1770 | int __init ndisc_init(void) | ||
1771 | { | ||
1772 | int err; | ||
1773 | |||
1774 | err = register_pernet_subsys(&ndisc_net_ops); | ||
1775 | if (err) | ||
1776 | return err; | ||
1771 | /* | 1777 | /* |
1772 | * Initialize the neighbour table | 1778 | * Initialize the neighbour table |
1773 | */ | 1779 | */ |
1774 | |||
1775 | neigh_table_init(&nd_tbl); | 1780 | neigh_table_init(&nd_tbl); |
1776 | 1781 | ||
1777 | #ifdef CONFIG_SYSCTL | 1782 | #ifdef CONFIG_SYSCTL |
1778 | neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, | 1783 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, |
1779 | "ipv6", | 1784 | NET_IPV6_NEIGH, "ipv6", |
1780 | &ndisc_ifinfo_sysctl_change, | 1785 | &ndisc_ifinfo_sysctl_change, |
1781 | &ndisc_ifinfo_sysctl_strategy); | 1786 | &ndisc_ifinfo_sysctl_strategy); |
1787 | if (err) | ||
1788 | goto out_unregister_pernet; | ||
1782 | #endif | 1789 | #endif |
1790 | err = register_netdevice_notifier(&ndisc_netdev_notifier); | ||
1791 | if (err) | ||
1792 | goto out_unregister_sysctl; | ||
1793 | out: | ||
1794 | return err; | ||
1783 | 1795 | ||
1784 | register_netdevice_notifier(&ndisc_netdev_notifier); | 1796 | out_unregister_sysctl: |
1785 | return 0; | 1797 | #ifdef CONFIG_SYSCTL |
1798 | neigh_sysctl_unregister(&nd_tbl.parms); | ||
1799 | out_unregister_pernet: | ||
1800 | #endif | ||
1801 | unregister_pernet_subsys(&ndisc_net_ops); | ||
1802 | goto out; | ||
1786 | } | 1803 | } |
1787 | 1804 | ||
1788 | void ndisc_cleanup(void) | 1805 | void ndisc_cleanup(void) |
@@ -1792,6 +1809,5 @@ void ndisc_cleanup(void) | |||
1792 | neigh_sysctl_unregister(&nd_tbl.parms); | 1809 | neigh_sysctl_unregister(&nd_tbl.parms); |
1793 | #endif | 1810 | #endif |
1794 | neigh_table_clear(&nd_tbl); | 1811 | neigh_table_clear(&nd_tbl); |
1795 | sock_release(ndisc_socket); | 1812 | unregister_pernet_subsys(&ndisc_net_ops); |
1796 | ndisc_socket = NULL; /* For safety. */ | ||
1797 | } | 1813 | } |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 2e06724dc348..aed51bcc66b4 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -23,7 +23,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
23 | .saddr = iph->saddr, } }, | 23 | .saddr = iph->saddr, } }, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | dst = ip6_route_output(skb->sk, &fl); | 26 | dst = ip6_route_output(&init_net, skb->sk, &fl); |
27 | 27 | ||
28 | #ifdef CONFIG_XFRM | 28 | #ifdef CONFIG_XFRM |
29 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | 29 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && |
@@ -86,7 +86,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
86 | 86 | ||
87 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) | 87 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) |
88 | { | 88 | { |
89 | *dst = ip6_route_output(NULL, fl); | 89 | *dst = ip6_route_output(&init_net, NULL, fl); |
90 | return (*dst)->error; | 90 | return (*dst)->error; |
91 | } | 91 | } |
92 | 92 | ||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 8d366f7f2a9a..92a36c9e5402 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -484,7 +484,7 @@ ipq_rcv_dev_event(struct notifier_block *this, | |||
484 | { | 484 | { |
485 | struct net_device *dev = ptr; | 485 | struct net_device *dev = ptr; |
486 | 486 | ||
487 | if (dev->nd_net != &init_net) | 487 | if (dev_net(dev) != &init_net) |
488 | return NOTIFY_DONE; | 488 | return NOTIFY_DONE; |
489 | 489 | ||
490 | /* Drop any packets associated with the downed device */ | 490 | /* Drop any packets associated with the downed device */ |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index bf9bb6e55bb5..70ef0d276cc0 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -55,7 +55,7 @@ MODULE_DESCRIPTION("IPv6 packet filter"); | |||
55 | do { \ | 55 | do { \ |
56 | if (!(x)) \ | 56 | if (!(x)) \ |
57 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ | 57 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ |
58 | __FUNCTION__, __FILE__, __LINE__); \ | 58 | __func__, __FILE__, __LINE__); \ |
59 | } while(0) | 59 | } while(0) |
60 | #else | 60 | #else |
61 | #define IP_NF_ASSERT(x) | 61 | #define IP_NF_ASSERT(x) |
@@ -1879,11 +1879,11 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, | |||
1879 | 1879 | ||
1880 | switch (cmd) { | 1880 | switch (cmd) { |
1881 | case IP6T_SO_SET_REPLACE: | 1881 | case IP6T_SO_SET_REPLACE: |
1882 | ret = compat_do_replace(sk->sk_net, user, len); | 1882 | ret = compat_do_replace(sock_net(sk), user, len); |
1883 | break; | 1883 | break; |
1884 | 1884 | ||
1885 | case IP6T_SO_SET_ADD_COUNTERS: | 1885 | case IP6T_SO_SET_ADD_COUNTERS: |
1886 | ret = do_add_counters(sk->sk_net, user, len, 1); | 1886 | ret = do_add_counters(sock_net(sk), user, len, 1); |
1887 | break; | 1887 | break; |
1888 | 1888 | ||
1889 | default: | 1889 | default: |
@@ -1990,10 +1990,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1990 | 1990 | ||
1991 | switch (cmd) { | 1991 | switch (cmd) { |
1992 | case IP6T_SO_GET_INFO: | 1992 | case IP6T_SO_GET_INFO: |
1993 | ret = get_info(sk->sk_net, user, len, 1); | 1993 | ret = get_info(sock_net(sk), user, len, 1); |
1994 | break; | 1994 | break; |
1995 | case IP6T_SO_GET_ENTRIES: | 1995 | case IP6T_SO_GET_ENTRIES: |
1996 | ret = compat_get_entries(sk->sk_net, user, len); | 1996 | ret = compat_get_entries(sock_net(sk), user, len); |
1997 | break; | 1997 | break; |
1998 | default: | 1998 | default: |
1999 | ret = do_ip6t_get_ctl(sk, cmd, user, len); | 1999 | ret = do_ip6t_get_ctl(sk, cmd, user, len); |
@@ -2012,11 +2012,11 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2012 | 2012 | ||
2013 | switch (cmd) { | 2013 | switch (cmd) { |
2014 | case IP6T_SO_SET_REPLACE: | 2014 | case IP6T_SO_SET_REPLACE: |
2015 | ret = do_replace(sk->sk_net, user, len); | 2015 | ret = do_replace(sock_net(sk), user, len); |
2016 | break; | 2016 | break; |
2017 | 2017 | ||
2018 | case IP6T_SO_SET_ADD_COUNTERS: | 2018 | case IP6T_SO_SET_ADD_COUNTERS: |
2019 | ret = do_add_counters(sk->sk_net, user, len, 0); | 2019 | ret = do_add_counters(sock_net(sk), user, len, 0); |
2020 | break; | 2020 | break; |
2021 | 2021 | ||
2022 | default: | 2022 | default: |
@@ -2037,11 +2037,11 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2037 | 2037 | ||
2038 | switch (cmd) { | 2038 | switch (cmd) { |
2039 | case IP6T_SO_GET_INFO: | 2039 | case IP6T_SO_GET_INFO: |
2040 | ret = get_info(sk->sk_net, user, len, 0); | 2040 | ret = get_info(sock_net(sk), user, len, 0); |
2041 | break; | 2041 | break; |
2042 | 2042 | ||
2043 | case IP6T_SO_GET_ENTRIES: | 2043 | case IP6T_SO_GET_ENTRIES: |
2044 | ret = get_entries(sk->sk_net, user, len); | 2044 | ret = get_entries(sock_net(sk), user, len); |
2045 | break; | 2045 | break; |
2046 | 2046 | ||
2047 | case IP6T_SO_GET_REVISION_MATCH: | 2047 | case IP6T_SO_GET_REVISION_MATCH: |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b23baa635fe0..baf829075f6f 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -93,7 +93,7 @@ static void send_reset(struct sk_buff *oldskb) | |||
93 | fl.fl_ip_sport = otcph.dest; | 93 | fl.fl_ip_sport = otcph.dest; |
94 | fl.fl_ip_dport = otcph.source; | 94 | fl.fl_ip_dport = otcph.source; |
95 | security_skb_classify_flow(oldskb, &fl); | 95 | security_skb_classify_flow(oldskb, &fl); |
96 | dst = ip6_route_output(NULL, &fl); | 96 | dst = ip6_route_output(&init_net, NULL, &fl); |
97 | if (dst == NULL) | 97 | if (dst == NULL) |
98 | return; | 98 | return; |
99 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) | 99 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) |
@@ -177,7 +177,7 @@ reject_tg6(struct sk_buff *skb, const struct net_device *in, | |||
177 | { | 177 | { |
178 | const struct ip6t_reject_info *reject = targinfo; | 178 | const struct ip6t_reject_info *reject = targinfo; |
179 | 179 | ||
180 | pr_debug("%s: medium point\n", __FUNCTION__); | 180 | pr_debug("%s: medium point\n", __func__); |
181 | /* WARNING: This code causes reentry within ip6tables. | 181 | /* WARNING: This code causes reentry within ip6tables. |
182 | This means that the ip6tables jump stack is now crap. We | 182 | This means that the ip6tables jump stack is now crap. We |
183 | must return an absolute verdict. --RR */ | 183 | must return an absolute verdict. --RR */ |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 199ef379e501..364dc332532c 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -214,6 +214,9 @@ int snmp6_register_dev(struct inet6_dev *idev) | |||
214 | if (!idev || !idev->dev) | 214 | if (!idev || !idev->dev) |
215 | return -EINVAL; | 215 | return -EINVAL; |
216 | 216 | ||
217 | if (dev_net(idev->dev) != &init_net) | ||
218 | return 0; | ||
219 | |||
217 | if (!proc_net_devsnmp6) | 220 | if (!proc_net_devsnmp6) |
218 | return -ENOENT; | 221 | return -ENOENT; |
219 | 222 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8897ccf8086a..830da4603697 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -62,20 +62,9 @@ | |||
62 | #include <linux/seq_file.h> | 62 | #include <linux/seq_file.h> |
63 | 63 | ||
64 | static struct raw_hashinfo raw_v6_hashinfo = { | 64 | static struct raw_hashinfo raw_v6_hashinfo = { |
65 | .lock = __RW_LOCK_UNLOCKED(), | 65 | .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock), |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static void raw_v6_hash(struct sock *sk) | ||
69 | { | ||
70 | raw_hash_sk(sk, &raw_v6_hashinfo); | ||
71 | } | ||
72 | |||
73 | static void raw_v6_unhash(struct sock *sk) | ||
74 | { | ||
75 | raw_unhash_sk(sk, &raw_v6_hashinfo); | ||
76 | } | ||
77 | |||
78 | |||
79 | static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, | 68 | static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, |
80 | unsigned short num, struct in6_addr *loc_addr, | 69 | unsigned short num, struct in6_addr *loc_addr, |
81 | struct in6_addr *rmt_addr, int dif) | 70 | struct in6_addr *rmt_addr, int dif) |
@@ -87,7 +76,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, | |||
87 | if (inet_sk(sk)->num == num) { | 76 | if (inet_sk(sk)->num == num) { |
88 | struct ipv6_pinfo *np = inet6_sk(sk); | 77 | struct ipv6_pinfo *np = inet6_sk(sk); |
89 | 78 | ||
90 | if (sk->sk_net != net) | 79 | if (!net_eq(sock_net(sk), net)) |
91 | continue; | 80 | continue; |
92 | 81 | ||
93 | if (!ipv6_addr_any(&np->daddr) && | 82 | if (!ipv6_addr_any(&np->daddr) && |
@@ -187,7 +176,7 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
187 | if (sk == NULL) | 176 | if (sk == NULL) |
188 | goto out; | 177 | goto out; |
189 | 178 | ||
190 | net = skb->dev->nd_net; | 179 | net = dev_net(skb->dev); |
191 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); | 180 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); |
192 | 181 | ||
193 | while (sk) { | 182 | while (sk) { |
@@ -291,7 +280,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
291 | if (!sk->sk_bound_dev_if) | 280 | if (!sk->sk_bound_dev_if) |
292 | goto out; | 281 | goto out; |
293 | 282 | ||
294 | dev = dev_get_by_index(sk->sk_net, sk->sk_bound_dev_if); | 283 | dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); |
295 | if (!dev) { | 284 | if (!dev) { |
296 | err = -ENODEV; | 285 | err = -ENODEV; |
297 | goto out; | 286 | goto out; |
@@ -304,7 +293,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
304 | v4addr = LOOPBACK4_IPV6; | 293 | v4addr = LOOPBACK4_IPV6; |
305 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 294 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
306 | err = -EADDRNOTAVAIL; | 295 | err = -EADDRNOTAVAIL; |
307 | if (!ipv6_chk_addr(sk->sk_net, &addr->sin6_addr, | 296 | if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, |
308 | dev, 0)) { | 297 | dev, 0)) { |
309 | if (dev) | 298 | if (dev) |
310 | dev_put(dev); | 299 | dev_put(dev); |
@@ -374,7 +363,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
374 | if (sk != NULL) { | 363 | if (sk != NULL) { |
375 | saddr = &ipv6_hdr(skb)->saddr; | 364 | saddr = &ipv6_hdr(skb)->saddr; |
376 | daddr = &ipv6_hdr(skb)->daddr; | 365 | daddr = &ipv6_hdr(skb)->daddr; |
377 | net = skb->dev->nd_net; | 366 | net = dev_net(skb->dev); |
378 | 367 | ||
379 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, | 368 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, |
380 | IP6CB(skb)->iif))) { | 369 | IP6CB(skb)->iif))) { |
@@ -896,9 +885,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
896 | else | 885 | else |
897 | hlimit = np->hop_limit; | 886 | hlimit = np->hop_limit; |
898 | if (hlimit < 0) | 887 | if (hlimit < 0) |
899 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 888 | hlimit = ip6_dst_hoplimit(dst); |
900 | if (hlimit < 0) | ||
901 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
902 | } | 889 | } |
903 | 890 | ||
904 | if (tclass < 0) { | 891 | if (tclass < 0) { |
@@ -1201,9 +1188,10 @@ struct proto rawv6_prot = { | |||
1201 | .recvmsg = rawv6_recvmsg, | 1188 | .recvmsg = rawv6_recvmsg, |
1202 | .bind = rawv6_bind, | 1189 | .bind = rawv6_bind, |
1203 | .backlog_rcv = rawv6_rcv_skb, | 1190 | .backlog_rcv = rawv6_rcv_skb, |
1204 | .hash = raw_v6_hash, | 1191 | .hash = raw_hash_sk, |
1205 | .unhash = raw_v6_unhash, | 1192 | .unhash = raw_unhash_sk, |
1206 | .obj_size = sizeof(struct raw6_sock), | 1193 | .obj_size = sizeof(struct raw6_sock), |
1194 | .h.raw_hash = &raw_v6_hashinfo, | ||
1207 | #ifdef CONFIG_COMPAT | 1195 | #ifdef CONFIG_COMPAT |
1208 | .compat_setsockopt = compat_rawv6_setsockopt, | 1196 | .compat_setsockopt = compat_rawv6_setsockopt, |
1209 | .compat_getsockopt = compat_rawv6_getsockopt, | 1197 | .compat_getsockopt = compat_rawv6_getsockopt, |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index f936d045a39d..4e1447634f36 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -600,7 +600,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
600 | return 1; | 600 | return 1; |
601 | } | 601 | } |
602 | 602 | ||
603 | net = skb->dev->nd_net; | 603 | net = dev_net(skb->dev); |
604 | if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) | 604 | if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) |
605 | ip6_evictor(net, ip6_dst_idev(skb->dst)); | 605 | ip6_evictor(net, ip6_dst_idev(skb->dst)); |
606 | 606 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e8b241cb60bc..cd82b6db35ff 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/if_arp.h> | 40 | #include <linux/if_arp.h> |
41 | #include <linux/proc_fs.h> | 41 | #include <linux/proc_fs.h> |
42 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
43 | #include <linux/nsproxy.h> | ||
43 | #include <net/net_namespace.h> | 44 | #include <net/net_namespace.h> |
44 | #include <net/snmp.h> | 45 | #include <net/snmp.h> |
45 | #include <net/ipv6.h> | 46 | #include <net/ipv6.h> |
@@ -87,14 +88,16 @@ static void ip6_link_failure(struct sk_buff *skb); | |||
87 | static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); | 88 | static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); |
88 | 89 | ||
89 | #ifdef CONFIG_IPV6_ROUTE_INFO | 90 | #ifdef CONFIG_IPV6_ROUTE_INFO |
90 | static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, | 91 | static struct rt6_info *rt6_add_route_info(struct net *net, |
92 | struct in6_addr *prefix, int prefixlen, | ||
91 | struct in6_addr *gwaddr, int ifindex, | 93 | struct in6_addr *gwaddr, int ifindex, |
92 | unsigned pref); | 94 | unsigned pref); |
93 | static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, | 95 | static struct rt6_info *rt6_get_route_info(struct net *net, |
96 | struct in6_addr *prefix, int prefixlen, | ||
94 | struct in6_addr *gwaddr, int ifindex); | 97 | struct in6_addr *gwaddr, int ifindex); |
95 | #endif | 98 | #endif |
96 | 99 | ||
97 | static struct dst_ops ip6_dst_ops = { | 100 | static struct dst_ops ip6_dst_ops_template = { |
98 | .family = AF_INET6, | 101 | .family = AF_INET6, |
99 | .protocol = __constant_htons(ETH_P_IPV6), | 102 | .protocol = __constant_htons(ETH_P_IPV6), |
100 | .gc = ip6_dst_gc, | 103 | .gc = ip6_dst_gc, |
@@ -124,7 +127,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
124 | .entries = ATOMIC_INIT(0), | 127 | .entries = ATOMIC_INIT(0), |
125 | }; | 128 | }; |
126 | 129 | ||
127 | struct rt6_info ip6_null_entry = { | 130 | static struct rt6_info ip6_null_entry_template = { |
128 | .u = { | 131 | .u = { |
129 | .dst = { | 132 | .dst = { |
130 | .__refcnt = ATOMIC_INIT(1), | 133 | .__refcnt = ATOMIC_INIT(1), |
@@ -134,8 +137,6 @@ struct rt6_info ip6_null_entry = { | |||
134 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 137 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
135 | .input = ip6_pkt_discard, | 138 | .input = ip6_pkt_discard, |
136 | .output = ip6_pkt_discard_out, | 139 | .output = ip6_pkt_discard_out, |
137 | .ops = &ip6_dst_ops, | ||
138 | .path = (struct dst_entry*)&ip6_null_entry, | ||
139 | } | 140 | } |
140 | }, | 141 | }, |
141 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 142 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
@@ -148,7 +149,7 @@ struct rt6_info ip6_null_entry = { | |||
148 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 149 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
149 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 150 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
150 | 151 | ||
151 | struct rt6_info ip6_prohibit_entry = { | 152 | struct rt6_info ip6_prohibit_entry_template = { |
152 | .u = { | 153 | .u = { |
153 | .dst = { | 154 | .dst = { |
154 | .__refcnt = ATOMIC_INIT(1), | 155 | .__refcnt = ATOMIC_INIT(1), |
@@ -158,8 +159,6 @@ struct rt6_info ip6_prohibit_entry = { | |||
158 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 159 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
159 | .input = ip6_pkt_prohibit, | 160 | .input = ip6_pkt_prohibit, |
160 | .output = ip6_pkt_prohibit_out, | 161 | .output = ip6_pkt_prohibit_out, |
161 | .ops = &ip6_dst_ops, | ||
162 | .path = (struct dst_entry*)&ip6_prohibit_entry, | ||
163 | } | 162 | } |
164 | }, | 163 | }, |
165 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 164 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
@@ -167,7 +166,7 @@ struct rt6_info ip6_prohibit_entry = { | |||
167 | .rt6i_ref = ATOMIC_INIT(1), | 166 | .rt6i_ref = ATOMIC_INIT(1), |
168 | }; | 167 | }; |
169 | 168 | ||
170 | struct rt6_info ip6_blk_hole_entry = { | 169 | static struct rt6_info ip6_blk_hole_entry_template = { |
171 | .u = { | 170 | .u = { |
172 | .dst = { | 171 | .dst = { |
173 | .__refcnt = ATOMIC_INIT(1), | 172 | .__refcnt = ATOMIC_INIT(1), |
@@ -177,8 +176,6 @@ struct rt6_info ip6_blk_hole_entry = { | |||
177 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 176 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
178 | .input = dst_discard, | 177 | .input = dst_discard, |
179 | .output = dst_discard, | 178 | .output = dst_discard, |
180 | .ops = &ip6_dst_ops, | ||
181 | .path = (struct dst_entry*)&ip6_blk_hole_entry, | ||
182 | } | 179 | } |
183 | }, | 180 | }, |
184 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 181 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
@@ -189,9 +186,9 @@ struct rt6_info ip6_blk_hole_entry = { | |||
189 | #endif | 186 | #endif |
190 | 187 | ||
191 | /* allocate dst with ip6_dst_ops */ | 188 | /* allocate dst with ip6_dst_ops */ |
192 | static __inline__ struct rt6_info *ip6_dst_alloc(void) | 189 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) |
193 | { | 190 | { |
194 | return (struct rt6_info *)dst_alloc(&ip6_dst_ops); | 191 | return (struct rt6_info *)dst_alloc(ops); |
195 | } | 192 | } |
196 | 193 | ||
197 | static void ip6_dst_destroy(struct dst_entry *dst) | 194 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -211,7 +208,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
211 | struct rt6_info *rt = (struct rt6_info *)dst; | 208 | struct rt6_info *rt = (struct rt6_info *)dst; |
212 | struct inet6_dev *idev = rt->rt6i_idev; | 209 | struct inet6_dev *idev = rt->rt6i_idev; |
213 | struct net_device *loopback_dev = | 210 | struct net_device *loopback_dev = |
214 | dev->nd_net->loopback_dev; | 211 | dev_net(dev)->loopback_dev; |
215 | 212 | ||
216 | if (dev != loopback_dev && idev != NULL && idev->dev == dev) { | 213 | if (dev != loopback_dev && idev != NULL && idev->dev == dev) { |
217 | struct inet6_dev *loopback_idev = | 214 | struct inet6_dev *loopback_idev = |
@@ -239,7 +236,8 @@ static inline int rt6_need_strict(struct in6_addr *daddr) | |||
239 | * Route lookup. Any table->tb6_lock is implied. | 236 | * Route lookup. Any table->tb6_lock is implied. |
240 | */ | 237 | */ |
241 | 238 | ||
242 | static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | 239 | static inline struct rt6_info *rt6_device_match(struct net *net, |
240 | struct rt6_info *rt, | ||
243 | int oif, | 241 | int oif, |
244 | int strict) | 242 | int strict) |
245 | { | 243 | { |
@@ -268,7 +266,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | |||
268 | return local; | 266 | return local; |
269 | 267 | ||
270 | if (strict) | 268 | if (strict) |
271 | return &ip6_null_entry; | 269 | return net->ipv6.ip6_null_entry; |
272 | } | 270 | } |
273 | return rt; | 271 | return rt; |
274 | } | 272 | } |
@@ -409,9 +407,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, | |||
409 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | 407 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) |
410 | { | 408 | { |
411 | struct rt6_info *match, *rt0; | 409 | struct rt6_info *match, *rt0; |
410 | struct net *net; | ||
412 | 411 | ||
413 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", | 412 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", |
414 | __FUNCTION__, fn->leaf, oif); | 413 | __func__, fn->leaf, oif); |
415 | 414 | ||
416 | rt0 = fn->rr_ptr; | 415 | rt0 = fn->rr_ptr; |
417 | if (!rt0) | 416 | if (!rt0) |
@@ -432,15 +431,17 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
432 | } | 431 | } |
433 | 432 | ||
434 | RT6_TRACE("%s() => %p\n", | 433 | RT6_TRACE("%s() => %p\n", |
435 | __FUNCTION__, match); | 434 | __func__, match); |
436 | 435 | ||
437 | return (match ? match : &ip6_null_entry); | 436 | net = dev_net(rt0->rt6i_dev); |
437 | return (match ? match : net->ipv6.ip6_null_entry); | ||
438 | } | 438 | } |
439 | 439 | ||
440 | #ifdef CONFIG_IPV6_ROUTE_INFO | 440 | #ifdef CONFIG_IPV6_ROUTE_INFO |
441 | int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | 441 | int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, |
442 | struct in6_addr *gwaddr) | 442 | struct in6_addr *gwaddr) |
443 | { | 443 | { |
444 | struct net *net = dev_net(dev); | ||
444 | struct route_info *rinfo = (struct route_info *) opt; | 445 | struct route_info *rinfo = (struct route_info *) opt; |
445 | struct in6_addr prefix_buf, *prefix; | 446 | struct in6_addr prefix_buf, *prefix; |
446 | unsigned int pref; | 447 | unsigned int pref; |
@@ -488,7 +489,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
488 | prefix = &prefix_buf; | 489 | prefix = &prefix_buf; |
489 | } | 490 | } |
490 | 491 | ||
491 | rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex); | 492 | rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr, |
493 | dev->ifindex); | ||
492 | 494 | ||
493 | if (rt && !lifetime) { | 495 | if (rt && !lifetime) { |
494 | ip6_del_rt(rt); | 496 | ip6_del_rt(rt); |
@@ -496,7 +498,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
496 | } | 498 | } |
497 | 499 | ||
498 | if (!rt && lifetime) | 500 | if (!rt && lifetime) |
499 | rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex, | 501 | rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex, |
500 | pref); | 502 | pref); |
501 | else if (rt) | 503 | else if (rt) |
502 | rt->rt6i_flags = RTF_ROUTEINFO | | 504 | rt->rt6i_flags = RTF_ROUTEINFO | |
@@ -515,9 +517,9 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
515 | } | 517 | } |
516 | #endif | 518 | #endif |
517 | 519 | ||
518 | #define BACKTRACK(saddr) \ | 520 | #define BACKTRACK(__net, saddr) \ |
519 | do { \ | 521 | do { \ |
520 | if (rt == &ip6_null_entry) { \ | 522 | if (rt == __net->ipv6.ip6_null_entry) { \ |
521 | struct fib6_node *pn; \ | 523 | struct fib6_node *pn; \ |
522 | while (1) { \ | 524 | while (1) { \ |
523 | if (fn->fn_flags & RTN_TL_ROOT) \ | 525 | if (fn->fn_flags & RTN_TL_ROOT) \ |
@@ -533,7 +535,8 @@ do { \ | |||
533 | } \ | 535 | } \ |
534 | } while(0) | 536 | } while(0) |
535 | 537 | ||
536 | static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, | 538 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
539 | struct fib6_table *table, | ||
537 | struct flowi *fl, int flags) | 540 | struct flowi *fl, int flags) |
538 | { | 541 | { |
539 | struct fib6_node *fn; | 542 | struct fib6_node *fn; |
@@ -543,8 +546,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, | |||
543 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 546 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
544 | restart: | 547 | restart: |
545 | rt = fn->leaf; | 548 | rt = fn->leaf; |
546 | rt = rt6_device_match(rt, fl->oif, flags); | 549 | rt = rt6_device_match(net, rt, fl->oif, flags); |
547 | BACKTRACK(&fl->fl6_src); | 550 | BACKTRACK(net, &fl->fl6_src); |
548 | out: | 551 | out: |
549 | dst_use(&rt->u.dst, jiffies); | 552 | dst_use(&rt->u.dst, jiffies); |
550 | read_unlock_bh(&table->tb6_lock); | 553 | read_unlock_bh(&table->tb6_lock); |
@@ -552,8 +555,8 @@ out: | |||
552 | 555 | ||
553 | } | 556 | } |
554 | 557 | ||
555 | struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | 558 | struct rt6_info *rt6_lookup(struct net *net, struct in6_addr *daddr, |
556 | int oif, int strict) | 559 | struct in6_addr *saddr, int oif, int strict) |
557 | { | 560 | { |
558 | struct flowi fl = { | 561 | struct flowi fl = { |
559 | .oif = oif, | 562 | .oif = oif, |
@@ -571,7 +574,7 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | |||
571 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 574 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
572 | } | 575 | } |
573 | 576 | ||
574 | dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); | 577 | dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup); |
575 | if (dst->error == 0) | 578 | if (dst->error == 0) |
576 | return (struct rt6_info *) dst; | 579 | return (struct rt6_info *) dst; |
577 | 580 | ||
@@ -604,7 +607,7 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) | |||
604 | int ip6_ins_rt(struct rt6_info *rt) | 607 | int ip6_ins_rt(struct rt6_info *rt) |
605 | { | 608 | { |
606 | struct nl_info info = { | 609 | struct nl_info info = { |
607 | .nl_net = &init_net, | 610 | .nl_net = dev_net(rt->rt6i_dev), |
608 | }; | 611 | }; |
609 | return __ip6_ins_rt(rt, &info); | 612 | return __ip6_ins_rt(rt, &info); |
610 | } | 613 | } |
@@ -660,8 +663,8 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
660 | return rt; | 663 | return rt; |
661 | } | 664 | } |
662 | 665 | ||
663 | static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif, | 666 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, |
664 | struct flowi *fl, int flags) | 667 | struct flowi *fl, int flags) |
665 | { | 668 | { |
666 | struct fib6_node *fn; | 669 | struct fib6_node *fn; |
667 | struct rt6_info *rt, *nrt; | 670 | struct rt6_info *rt, *nrt; |
@@ -680,8 +683,9 @@ restart_2: | |||
680 | 683 | ||
681 | restart: | 684 | restart: |
682 | rt = rt6_select(fn, oif, strict | reachable); | 685 | rt = rt6_select(fn, oif, strict | reachable); |
683 | BACKTRACK(&fl->fl6_src); | 686 | |
684 | if (rt == &ip6_null_entry || | 687 | BACKTRACK(net, &fl->fl6_src); |
688 | if (rt == net->ipv6.ip6_null_entry || | ||
685 | rt->rt6i_flags & RTF_CACHE) | 689 | rt->rt6i_flags & RTF_CACHE) |
686 | goto out; | 690 | goto out; |
687 | 691 | ||
@@ -699,7 +703,7 @@ restart: | |||
699 | } | 703 | } |
700 | 704 | ||
701 | dst_release(&rt->u.dst); | 705 | dst_release(&rt->u.dst); |
702 | rt = nrt ? : &ip6_null_entry; | 706 | rt = nrt ? : net->ipv6.ip6_null_entry; |
703 | 707 | ||
704 | dst_hold(&rt->u.dst); | 708 | dst_hold(&rt->u.dst); |
705 | if (nrt) { | 709 | if (nrt) { |
@@ -732,15 +736,16 @@ out2: | |||
732 | return rt; | 736 | return rt; |
733 | } | 737 | } |
734 | 738 | ||
735 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | 739 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, |
736 | struct flowi *fl, int flags) | 740 | struct flowi *fl, int flags) |
737 | { | 741 | { |
738 | return ip6_pol_route(table, fl->iif, fl, flags); | 742 | return ip6_pol_route(net, table, fl->iif, fl, flags); |
739 | } | 743 | } |
740 | 744 | ||
741 | void ip6_route_input(struct sk_buff *skb) | 745 | void ip6_route_input(struct sk_buff *skb) |
742 | { | 746 | { |
743 | struct ipv6hdr *iph = ipv6_hdr(skb); | 747 | struct ipv6hdr *iph = ipv6_hdr(skb); |
748 | struct net *net = dev_net(skb->dev); | ||
744 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 749 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
745 | struct flowi fl = { | 750 | struct flowi fl = { |
746 | .iif = skb->dev->ifindex, | 751 | .iif = skb->dev->ifindex, |
@@ -758,16 +763,17 @@ void ip6_route_input(struct sk_buff *skb) | |||
758 | if (rt6_need_strict(&iph->daddr)) | 763 | if (rt6_need_strict(&iph->daddr)) |
759 | flags |= RT6_LOOKUP_F_IFACE; | 764 | flags |= RT6_LOOKUP_F_IFACE; |
760 | 765 | ||
761 | skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); | 766 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); |
762 | } | 767 | } |
763 | 768 | ||
764 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | 769 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, |
765 | struct flowi *fl, int flags) | 770 | struct flowi *fl, int flags) |
766 | { | 771 | { |
767 | return ip6_pol_route(table, fl->oif, fl, flags); | 772 | return ip6_pol_route(net, table, fl->oif, fl, flags); |
768 | } | 773 | } |
769 | 774 | ||
770 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | 775 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, |
776 | struct flowi *fl) | ||
771 | { | 777 | { |
772 | int flags = 0; | 778 | int flags = 0; |
773 | 779 | ||
@@ -776,8 +782,17 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | |||
776 | 782 | ||
777 | if (!ipv6_addr_any(&fl->fl6_src)) | 783 | if (!ipv6_addr_any(&fl->fl6_src)) |
778 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 784 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
785 | else if (sk) { | ||
786 | unsigned int prefs = inet6_sk(sk)->srcprefs; | ||
787 | if (prefs & IPV6_PREFER_SRC_TMP) | ||
788 | flags |= RT6_LOOKUP_F_SRCPREF_TMP; | ||
789 | if (prefs & IPV6_PREFER_SRC_PUBLIC) | ||
790 | flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; | ||
791 | if (prefs & IPV6_PREFER_SRC_COA) | ||
792 | flags |= RT6_LOOKUP_F_SRCPREF_COA; | ||
793 | } | ||
779 | 794 | ||
780 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); | 795 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); |
781 | } | 796 | } |
782 | 797 | ||
783 | EXPORT_SYMBOL(ip6_route_output); | 798 | EXPORT_SYMBOL(ip6_route_output); |
@@ -886,12 +901,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
886 | 901 | ||
887 | static int ipv6_get_mtu(struct net_device *dev); | 902 | static int ipv6_get_mtu(struct net_device *dev); |
888 | 903 | ||
889 | static inline unsigned int ipv6_advmss(unsigned int mtu) | 904 | static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu) |
890 | { | 905 | { |
891 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); | 906 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); |
892 | 907 | ||
893 | if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss) | 908 | if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) |
894 | mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss; | 909 | mtu = net->ipv6.sysctl.ip6_rt_min_advmss; |
895 | 910 | ||
896 | /* | 911 | /* |
897 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and | 912 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and |
@@ -904,21 +919,21 @@ static inline unsigned int ipv6_advmss(unsigned int mtu) | |||
904 | return mtu; | 919 | return mtu; |
905 | } | 920 | } |
906 | 921 | ||
907 | static struct dst_entry *ndisc_dst_gc_list; | 922 | static struct dst_entry *icmp6_dst_gc_list; |
908 | static DEFINE_SPINLOCK(ndisc_lock); | 923 | static DEFINE_SPINLOCK(icmp6_dst_lock); |
909 | 924 | ||
910 | struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | 925 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
911 | struct neighbour *neigh, | 926 | struct neighbour *neigh, |
912 | struct in6_addr *addr, | 927 | struct in6_addr *addr) |
913 | int (*output)(struct sk_buff *)) | ||
914 | { | 928 | { |
915 | struct rt6_info *rt; | 929 | struct rt6_info *rt; |
916 | struct inet6_dev *idev = in6_dev_get(dev); | 930 | struct inet6_dev *idev = in6_dev_get(dev); |
931 | struct net *net = dev_net(dev); | ||
917 | 932 | ||
918 | if (unlikely(idev == NULL)) | 933 | if (unlikely(idev == NULL)) |
919 | return NULL; | 934 | return NULL; |
920 | 935 | ||
921 | rt = ip6_dst_alloc(); | 936 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
922 | if (unlikely(rt == NULL)) { | 937 | if (unlikely(rt == NULL)) { |
923 | in6_dev_put(idev); | 938 | in6_dev_put(idev); |
924 | goto out; | 939 | goto out; |
@@ -936,8 +951,8 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
936 | atomic_set(&rt->u.dst.__refcnt, 1); | 951 | atomic_set(&rt->u.dst.__refcnt, 1); |
937 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; | 952 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; |
938 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 953 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
939 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); | 954 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
940 | rt->u.dst.output = output; | 955 | rt->u.dst.output = ip6_output; |
941 | 956 | ||
942 | #if 0 /* there's no chance to use these for ndisc */ | 957 | #if 0 /* there's no chance to use these for ndisc */ |
943 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | 958 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST |
@@ -947,18 +962,18 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
947 | rt->rt6i_dst.plen = 128; | 962 | rt->rt6i_dst.plen = 128; |
948 | #endif | 963 | #endif |
949 | 964 | ||
950 | spin_lock_bh(&ndisc_lock); | 965 | spin_lock_bh(&icmp6_dst_lock); |
951 | rt->u.dst.next = ndisc_dst_gc_list; | 966 | rt->u.dst.next = icmp6_dst_gc_list; |
952 | ndisc_dst_gc_list = &rt->u.dst; | 967 | icmp6_dst_gc_list = &rt->u.dst; |
953 | spin_unlock_bh(&ndisc_lock); | 968 | spin_unlock_bh(&icmp6_dst_lock); |
954 | 969 | ||
955 | fib6_force_start_gc(); | 970 | fib6_force_start_gc(net); |
956 | 971 | ||
957 | out: | 972 | out: |
958 | return &rt->u.dst; | 973 | return &rt->u.dst; |
959 | } | 974 | } |
960 | 975 | ||
961 | int ndisc_dst_gc(int *more) | 976 | int icmp6_dst_gc(int *more) |
962 | { | 977 | { |
963 | struct dst_entry *dst, *next, **pprev; | 978 | struct dst_entry *dst, *next, **pprev; |
964 | int freed; | 979 | int freed; |
@@ -966,8 +981,8 @@ int ndisc_dst_gc(int *more) | |||
966 | next = NULL; | 981 | next = NULL; |
967 | freed = 0; | 982 | freed = 0; |
968 | 983 | ||
969 | spin_lock_bh(&ndisc_lock); | 984 | spin_lock_bh(&icmp6_dst_lock); |
970 | pprev = &ndisc_dst_gc_list; | 985 | pprev = &icmp6_dst_gc_list; |
971 | 986 | ||
972 | while ((dst = *pprev) != NULL) { | 987 | while ((dst = *pprev) != NULL) { |
973 | if (!atomic_read(&dst->__refcnt)) { | 988 | if (!atomic_read(&dst->__refcnt)) { |
@@ -980,30 +995,33 @@ int ndisc_dst_gc(int *more) | |||
980 | } | 995 | } |
981 | } | 996 | } |
982 | 997 | ||
983 | spin_unlock_bh(&ndisc_lock); | 998 | spin_unlock_bh(&icmp6_dst_lock); |
984 | 999 | ||
985 | return freed; | 1000 | return freed; |
986 | } | 1001 | } |
987 | 1002 | ||
988 | static int ip6_dst_gc(struct dst_ops *ops) | 1003 | static int ip6_dst_gc(struct dst_ops *ops) |
989 | { | 1004 | { |
990 | static unsigned expire = 30*HZ; | ||
991 | static unsigned long last_gc; | ||
992 | unsigned long now = jiffies; | 1005 | unsigned long now = jiffies; |
993 | 1006 | struct net *net = ops->dst_net; | |
994 | if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) && | 1007 | int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; |
995 | atomic_read(&ip6_dst_ops.entries) <= init_net.ipv6.sysctl.ip6_rt_max_size) | 1008 | int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; |
1009 | int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
1010 | int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
1011 | unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; | ||
1012 | |||
1013 | if (time_after(rt_last_gc + rt_min_interval, now) && | ||
1014 | atomic_read(&ops->entries) <= rt_max_size) | ||
996 | goto out; | 1015 | goto out; |
997 | 1016 | ||
998 | expire++; | 1017 | net->ipv6.ip6_rt_gc_expire++; |
999 | fib6_run_gc(expire); | 1018 | fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net); |
1000 | last_gc = now; | 1019 | net->ipv6.ip6_rt_last_gc = now; |
1001 | if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh) | 1020 | if (atomic_read(&ops->entries) < ops->gc_thresh) |
1002 | expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1; | 1021 | net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; |
1003 | |||
1004 | out: | 1022 | out: |
1005 | expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity; | 1023 | net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity; |
1006 | return (atomic_read(&ip6_dst_ops.entries) > init_net.ipv6.sysctl.ip6_rt_max_size); | 1024 | return (atomic_read(&ops->entries) > rt_max_size); |
1007 | } | 1025 | } |
1008 | 1026 | ||
1009 | /* Clean host part of a prefix. Not necessary in radix tree, | 1027 | /* Clean host part of a prefix. Not necessary in radix tree, |
@@ -1025,15 +1043,17 @@ static int ipv6_get_mtu(struct net_device *dev) | |||
1025 | return mtu; | 1043 | return mtu; |
1026 | } | 1044 | } |
1027 | 1045 | ||
1028 | int ipv6_get_hoplimit(struct net_device *dev) | 1046 | int ip6_dst_hoplimit(struct dst_entry *dst) |
1029 | { | 1047 | { |
1030 | int hoplimit = ipv6_devconf.hop_limit; | 1048 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); |
1031 | struct inet6_dev *idev; | 1049 | if (hoplimit < 0) { |
1032 | 1050 | struct net_device *dev = dst->dev; | |
1033 | idev = in6_dev_get(dev); | 1051 | struct inet6_dev *idev = in6_dev_get(dev); |
1034 | if (idev) { | 1052 | if (idev) { |
1035 | hoplimit = idev->cnf.hop_limit; | 1053 | hoplimit = idev->cnf.hop_limit; |
1036 | in6_dev_put(idev); | 1054 | in6_dev_put(idev); |
1055 | } else | ||
1056 | hoplimit = ipv6_devconf.hop_limit; | ||
1037 | } | 1057 | } |
1038 | return hoplimit; | 1058 | return hoplimit; |
1039 | } | 1059 | } |
@@ -1045,6 +1065,7 @@ int ipv6_get_hoplimit(struct net_device *dev) | |||
1045 | int ip6_route_add(struct fib6_config *cfg) | 1065 | int ip6_route_add(struct fib6_config *cfg) |
1046 | { | 1066 | { |
1047 | int err; | 1067 | int err; |
1068 | struct net *net = cfg->fc_nlinfo.nl_net; | ||
1048 | struct rt6_info *rt = NULL; | 1069 | struct rt6_info *rt = NULL; |
1049 | struct net_device *dev = NULL; | 1070 | struct net_device *dev = NULL; |
1050 | struct inet6_dev *idev = NULL; | 1071 | struct inet6_dev *idev = NULL; |
@@ -1059,7 +1080,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1059 | #endif | 1080 | #endif |
1060 | if (cfg->fc_ifindex) { | 1081 | if (cfg->fc_ifindex) { |
1061 | err = -ENODEV; | 1082 | err = -ENODEV; |
1062 | dev = dev_get_by_index(&init_net, cfg->fc_ifindex); | 1083 | dev = dev_get_by_index(net, cfg->fc_ifindex); |
1063 | if (!dev) | 1084 | if (!dev) |
1064 | goto out; | 1085 | goto out; |
1065 | idev = in6_dev_get(dev); | 1086 | idev = in6_dev_get(dev); |
@@ -1070,13 +1091,13 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1070 | if (cfg->fc_metric == 0) | 1091 | if (cfg->fc_metric == 0) |
1071 | cfg->fc_metric = IP6_RT_PRIO_USER; | 1092 | cfg->fc_metric = IP6_RT_PRIO_USER; |
1072 | 1093 | ||
1073 | table = fib6_new_table(cfg->fc_table); | 1094 | table = fib6_new_table(net, cfg->fc_table); |
1074 | if (table == NULL) { | 1095 | if (table == NULL) { |
1075 | err = -ENOBUFS; | 1096 | err = -ENOBUFS; |
1076 | goto out; | 1097 | goto out; |
1077 | } | 1098 | } |
1078 | 1099 | ||
1079 | rt = ip6_dst_alloc(); | 1100 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
1080 | 1101 | ||
1081 | if (rt == NULL) { | 1102 | if (rt == NULL) { |
1082 | err = -ENOMEM; | 1103 | err = -ENOMEM; |
@@ -1117,12 +1138,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1117 | if ((cfg->fc_flags & RTF_REJECT) || | 1138 | if ((cfg->fc_flags & RTF_REJECT) || |
1118 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { | 1139 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { |
1119 | /* hold loopback dev/idev if we haven't done so. */ | 1140 | /* hold loopback dev/idev if we haven't done so. */ |
1120 | if (dev != init_net.loopback_dev) { | 1141 | if (dev != net->loopback_dev) { |
1121 | if (dev) { | 1142 | if (dev) { |
1122 | dev_put(dev); | 1143 | dev_put(dev); |
1123 | in6_dev_put(idev); | 1144 | in6_dev_put(idev); |
1124 | } | 1145 | } |
1125 | dev = init_net.loopback_dev; | 1146 | dev = net->loopback_dev; |
1126 | dev_hold(dev); | 1147 | dev_hold(dev); |
1127 | idev = in6_dev_get(dev); | 1148 | idev = in6_dev_get(dev); |
1128 | if (!idev) { | 1149 | if (!idev) { |
@@ -1159,7 +1180,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1159 | if (!(gwa_type&IPV6_ADDR_UNICAST)) | 1180 | if (!(gwa_type&IPV6_ADDR_UNICAST)) |
1160 | goto out; | 1181 | goto out; |
1161 | 1182 | ||
1162 | grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1); | 1183 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); |
1163 | 1184 | ||
1164 | err = -EHOSTUNREACH; | 1185 | err = -EHOSTUNREACH; |
1165 | if (grt == NULL) | 1186 | if (grt == NULL) |
@@ -1226,10 +1247,13 @@ install_route: | |||
1226 | if (!rt->u.dst.metrics[RTAX_MTU-1]) | 1247 | if (!rt->u.dst.metrics[RTAX_MTU-1]) |
1227 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1248 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); |
1228 | if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) | 1249 | if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) |
1229 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); | 1250 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
1230 | rt->u.dst.dev = dev; | 1251 | rt->u.dst.dev = dev; |
1231 | rt->rt6i_idev = idev; | 1252 | rt->rt6i_idev = idev; |
1232 | rt->rt6i_table = table; | 1253 | rt->rt6i_table = table; |
1254 | |||
1255 | cfg->fc_nlinfo.nl_net = dev_net(dev); | ||
1256 | |||
1233 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); | 1257 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); |
1234 | 1258 | ||
1235 | out: | 1259 | out: |
@@ -1246,8 +1270,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1246 | { | 1270 | { |
1247 | int err; | 1271 | int err; |
1248 | struct fib6_table *table; | 1272 | struct fib6_table *table; |
1273 | struct net *net = dev_net(rt->rt6i_dev); | ||
1249 | 1274 | ||
1250 | if (rt == &ip6_null_entry) | 1275 | if (rt == net->ipv6.ip6_null_entry) |
1251 | return -ENOENT; | 1276 | return -ENOENT; |
1252 | 1277 | ||
1253 | table = rt->rt6i_table; | 1278 | table = rt->rt6i_table; |
@@ -1264,7 +1289,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1264 | int ip6_del_rt(struct rt6_info *rt) | 1289 | int ip6_del_rt(struct rt6_info *rt) |
1265 | { | 1290 | { |
1266 | struct nl_info info = { | 1291 | struct nl_info info = { |
1267 | .nl_net = &init_net, | 1292 | .nl_net = dev_net(rt->rt6i_dev), |
1268 | }; | 1293 | }; |
1269 | return __ip6_del_rt(rt, &info); | 1294 | return __ip6_del_rt(rt, &info); |
1270 | } | 1295 | } |
@@ -1276,7 +1301,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1276 | struct rt6_info *rt; | 1301 | struct rt6_info *rt; |
1277 | int err = -ESRCH; | 1302 | int err = -ESRCH; |
1278 | 1303 | ||
1279 | table = fib6_get_table(cfg->fc_table); | 1304 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); |
1280 | if (table == NULL) | 1305 | if (table == NULL) |
1281 | return err; | 1306 | return err; |
1282 | 1307 | ||
@@ -1316,7 +1341,8 @@ struct ip6rd_flowi { | |||
1316 | struct in6_addr gateway; | 1341 | struct in6_addr gateway; |
1317 | }; | 1342 | }; |
1318 | 1343 | ||
1319 | static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, | 1344 | static struct rt6_info *__ip6_route_redirect(struct net *net, |
1345 | struct fib6_table *table, | ||
1320 | struct flowi *fl, | 1346 | struct flowi *fl, |
1321 | int flags) | 1347 | int flags) |
1322 | { | 1348 | { |
@@ -1359,8 +1385,8 @@ restart: | |||
1359 | } | 1385 | } |
1360 | 1386 | ||
1361 | if (!rt) | 1387 | if (!rt) |
1362 | rt = &ip6_null_entry; | 1388 | rt = net->ipv6.ip6_null_entry; |
1363 | BACKTRACK(&fl->fl6_src); | 1389 | BACKTRACK(net, &fl->fl6_src); |
1364 | out: | 1390 | out: |
1365 | dst_hold(&rt->u.dst); | 1391 | dst_hold(&rt->u.dst); |
1366 | 1392 | ||
@@ -1375,6 +1401,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1375 | struct net_device *dev) | 1401 | struct net_device *dev) |
1376 | { | 1402 | { |
1377 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 1403 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
1404 | struct net *net = dev_net(dev); | ||
1378 | struct ip6rd_flowi rdfl = { | 1405 | struct ip6rd_flowi rdfl = { |
1379 | .fl = { | 1406 | .fl = { |
1380 | .oif = dev->ifindex, | 1407 | .oif = dev->ifindex, |
@@ -1391,7 +1418,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1391 | if (rt6_need_strict(dest)) | 1418 | if (rt6_need_strict(dest)) |
1392 | flags |= RT6_LOOKUP_F_IFACE; | 1419 | flags |= RT6_LOOKUP_F_IFACE; |
1393 | 1420 | ||
1394 | return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); | 1421 | return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl, |
1422 | flags, __ip6_route_redirect); | ||
1395 | } | 1423 | } |
1396 | 1424 | ||
1397 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | 1425 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, |
@@ -1400,10 +1428,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1400 | { | 1428 | { |
1401 | struct rt6_info *rt, *nrt = NULL; | 1429 | struct rt6_info *rt, *nrt = NULL; |
1402 | struct netevent_redirect netevent; | 1430 | struct netevent_redirect netevent; |
1431 | struct net *net = dev_net(neigh->dev); | ||
1403 | 1432 | ||
1404 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); | 1433 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); |
1405 | 1434 | ||
1406 | if (rt == &ip6_null_entry) { | 1435 | if (rt == net->ipv6.ip6_null_entry) { |
1407 | if (net_ratelimit()) | 1436 | if (net_ratelimit()) |
1408 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " | 1437 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " |
1409 | "for redirect target\n"); | 1438 | "for redirect target\n"); |
@@ -1448,7 +1477,8 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1448 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1477 | nrt->rt6i_nexthop = neigh_clone(neigh); |
1449 | /* Reset pmtu, it may be better */ | 1478 | /* Reset pmtu, it may be better */ |
1450 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1479 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); |
1451 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst)); | 1480 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), |
1481 | dst_mtu(&nrt->u.dst)); | ||
1452 | 1482 | ||
1453 | if (ip6_ins_rt(nrt)) | 1483 | if (ip6_ins_rt(nrt)) |
1454 | goto out; | 1484 | goto out; |
@@ -1476,9 +1506,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1476 | struct net_device *dev, u32 pmtu) | 1506 | struct net_device *dev, u32 pmtu) |
1477 | { | 1507 | { |
1478 | struct rt6_info *rt, *nrt; | 1508 | struct rt6_info *rt, *nrt; |
1509 | struct net *net = dev_net(dev); | ||
1479 | int allfrag = 0; | 1510 | int allfrag = 0; |
1480 | 1511 | ||
1481 | rt = rt6_lookup(daddr, saddr, dev->ifindex, 0); | 1512 | rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0); |
1482 | if (rt == NULL) | 1513 | if (rt == NULL) |
1483 | return; | 1514 | return; |
1484 | 1515 | ||
@@ -1511,7 +1542,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1511 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1542 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; |
1512 | if (allfrag) | 1543 | if (allfrag) |
1513 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1544 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
1514 | dst_set_expires(&rt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires); | 1545 | dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1515 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1546 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
1516 | goto out; | 1547 | goto out; |
1517 | } | 1548 | } |
@@ -1537,7 +1568,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1537 | * which is 10 mins. After 10 mins the decreased pmtu is expired | 1568 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
1538 | * and detecting PMTU increase will be automatically happened. | 1569 | * and detecting PMTU increase will be automatically happened. |
1539 | */ | 1570 | */ |
1540 | dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires); | 1571 | dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1541 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1572 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; |
1542 | 1573 | ||
1543 | ip6_ins_rt(nrt); | 1574 | ip6_ins_rt(nrt); |
@@ -1552,7 +1583,8 @@ out: | |||
1552 | 1583 | ||
1553 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1584 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) |
1554 | { | 1585 | { |
1555 | struct rt6_info *rt = ip6_dst_alloc(); | 1586 | struct net *net = dev_net(ort->rt6i_dev); |
1587 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1556 | 1588 | ||
1557 | if (rt) { | 1589 | if (rt) { |
1558 | rt->u.dst.input = ort->u.dst.input; | 1590 | rt->u.dst.input = ort->u.dst.input; |
@@ -1583,14 +1615,15 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1583 | } | 1615 | } |
1584 | 1616 | ||
1585 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1617 | #ifdef CONFIG_IPV6_ROUTE_INFO |
1586 | static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, | 1618 | static struct rt6_info *rt6_get_route_info(struct net *net, |
1619 | struct in6_addr *prefix, int prefixlen, | ||
1587 | struct in6_addr *gwaddr, int ifindex) | 1620 | struct in6_addr *gwaddr, int ifindex) |
1588 | { | 1621 | { |
1589 | struct fib6_node *fn; | 1622 | struct fib6_node *fn; |
1590 | struct rt6_info *rt = NULL; | 1623 | struct rt6_info *rt = NULL; |
1591 | struct fib6_table *table; | 1624 | struct fib6_table *table; |
1592 | 1625 | ||
1593 | table = fib6_get_table(RT6_TABLE_INFO); | 1626 | table = fib6_get_table(net, RT6_TABLE_INFO); |
1594 | if (table == NULL) | 1627 | if (table == NULL) |
1595 | return NULL; | 1628 | return NULL; |
1596 | 1629 | ||
@@ -1614,7 +1647,8 @@ out: | |||
1614 | return rt; | 1647 | return rt; |
1615 | } | 1648 | } |
1616 | 1649 | ||
1617 | static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, | 1650 | static struct rt6_info *rt6_add_route_info(struct net *net, |
1651 | struct in6_addr *prefix, int prefixlen, | ||
1618 | struct in6_addr *gwaddr, int ifindex, | 1652 | struct in6_addr *gwaddr, int ifindex, |
1619 | unsigned pref) | 1653 | unsigned pref) |
1620 | { | 1654 | { |
@@ -1625,6 +1659,9 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle | |||
1625 | .fc_dst_len = prefixlen, | 1659 | .fc_dst_len = prefixlen, |
1626 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | | 1660 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | |
1627 | RTF_UP | RTF_PREF(pref), | 1661 | RTF_UP | RTF_PREF(pref), |
1662 | .fc_nlinfo.pid = 0, | ||
1663 | .fc_nlinfo.nlh = NULL, | ||
1664 | .fc_nlinfo.nl_net = net, | ||
1628 | }; | 1665 | }; |
1629 | 1666 | ||
1630 | ipv6_addr_copy(&cfg.fc_dst, prefix); | 1667 | ipv6_addr_copy(&cfg.fc_dst, prefix); |
@@ -1636,7 +1673,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle | |||
1636 | 1673 | ||
1637 | ip6_route_add(&cfg); | 1674 | ip6_route_add(&cfg); |
1638 | 1675 | ||
1639 | return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); | 1676 | return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex); |
1640 | } | 1677 | } |
1641 | #endif | 1678 | #endif |
1642 | 1679 | ||
@@ -1645,7 +1682,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1645 | struct rt6_info *rt; | 1682 | struct rt6_info *rt; |
1646 | struct fib6_table *table; | 1683 | struct fib6_table *table; |
1647 | 1684 | ||
1648 | table = fib6_get_table(RT6_TABLE_DFLT); | 1685 | table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); |
1649 | if (table == NULL) | 1686 | if (table == NULL) |
1650 | return NULL; | 1687 | return NULL; |
1651 | 1688 | ||
@@ -1674,6 +1711,9 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1674 | .fc_ifindex = dev->ifindex, | 1711 | .fc_ifindex = dev->ifindex, |
1675 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | | 1712 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | |
1676 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), | 1713 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), |
1714 | .fc_nlinfo.pid = 0, | ||
1715 | .fc_nlinfo.nlh = NULL, | ||
1716 | .fc_nlinfo.nl_net = dev_net(dev), | ||
1677 | }; | 1717 | }; |
1678 | 1718 | ||
1679 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1719 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); |
@@ -1683,13 +1723,13 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1683 | return rt6_get_dflt_router(gwaddr, dev); | 1723 | return rt6_get_dflt_router(gwaddr, dev); |
1684 | } | 1724 | } |
1685 | 1725 | ||
1686 | void rt6_purge_dflt_routers(void) | 1726 | void rt6_purge_dflt_routers(struct net *net) |
1687 | { | 1727 | { |
1688 | struct rt6_info *rt; | 1728 | struct rt6_info *rt; |
1689 | struct fib6_table *table; | 1729 | struct fib6_table *table; |
1690 | 1730 | ||
1691 | /* NOTE: Keep consistent with rt6_get_dflt_router */ | 1731 | /* NOTE: Keep consistent with rt6_get_dflt_router */ |
1692 | table = fib6_get_table(RT6_TABLE_DFLT); | 1732 | table = fib6_get_table(net, RT6_TABLE_DFLT); |
1693 | if (table == NULL) | 1733 | if (table == NULL) |
1694 | return; | 1734 | return; |
1695 | 1735 | ||
@@ -1706,7 +1746,8 @@ restart: | |||
1706 | read_unlock_bh(&table->tb6_lock); | 1746 | read_unlock_bh(&table->tb6_lock); |
1707 | } | 1747 | } |
1708 | 1748 | ||
1709 | static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, | 1749 | static void rtmsg_to_fib6_config(struct net *net, |
1750 | struct in6_rtmsg *rtmsg, | ||
1710 | struct fib6_config *cfg) | 1751 | struct fib6_config *cfg) |
1711 | { | 1752 | { |
1712 | memset(cfg, 0, sizeof(*cfg)); | 1753 | memset(cfg, 0, sizeof(*cfg)); |
@@ -1719,14 +1760,14 @@ static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, | |||
1719 | cfg->fc_src_len = rtmsg->rtmsg_src_len; | 1760 | cfg->fc_src_len = rtmsg->rtmsg_src_len; |
1720 | cfg->fc_flags = rtmsg->rtmsg_flags; | 1761 | cfg->fc_flags = rtmsg->rtmsg_flags; |
1721 | 1762 | ||
1722 | cfg->fc_nlinfo.nl_net = &init_net; | 1763 | cfg->fc_nlinfo.nl_net = net; |
1723 | 1764 | ||
1724 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); | 1765 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); |
1725 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); | 1766 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); |
1726 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); | 1767 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); |
1727 | } | 1768 | } |
1728 | 1769 | ||
1729 | int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | 1770 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
1730 | { | 1771 | { |
1731 | struct fib6_config cfg; | 1772 | struct fib6_config cfg; |
1732 | struct in6_rtmsg rtmsg; | 1773 | struct in6_rtmsg rtmsg; |
@@ -1742,7 +1783,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1742 | if (err) | 1783 | if (err) |
1743 | return -EFAULT; | 1784 | return -EFAULT; |
1744 | 1785 | ||
1745 | rtmsg_to_fib6_config(&rtmsg, &cfg); | 1786 | rtmsg_to_fib6_config(net, &rtmsg, &cfg); |
1746 | 1787 | ||
1747 | rtnl_lock(); | 1788 | rtnl_lock(); |
1748 | switch (cmd) { | 1789 | switch (cmd) { |
@@ -1821,21 +1862,22 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1821 | const struct in6_addr *addr, | 1862 | const struct in6_addr *addr, |
1822 | int anycast) | 1863 | int anycast) |
1823 | { | 1864 | { |
1824 | struct rt6_info *rt = ip6_dst_alloc(); | 1865 | struct net *net = dev_net(idev->dev); |
1866 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1825 | 1867 | ||
1826 | if (rt == NULL) | 1868 | if (rt == NULL) |
1827 | return ERR_PTR(-ENOMEM); | 1869 | return ERR_PTR(-ENOMEM); |
1828 | 1870 | ||
1829 | dev_hold(init_net.loopback_dev); | 1871 | dev_hold(net->loopback_dev); |
1830 | in6_dev_hold(idev); | 1872 | in6_dev_hold(idev); |
1831 | 1873 | ||
1832 | rt->u.dst.flags = DST_HOST; | 1874 | rt->u.dst.flags = DST_HOST; |
1833 | rt->u.dst.input = ip6_input; | 1875 | rt->u.dst.input = ip6_input; |
1834 | rt->u.dst.output = ip6_output; | 1876 | rt->u.dst.output = ip6_output; |
1835 | rt->rt6i_dev = init_net.loopback_dev; | 1877 | rt->rt6i_dev = net->loopback_dev; |
1836 | rt->rt6i_idev = idev; | 1878 | rt->rt6i_idev = idev; |
1837 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1879 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
1838 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); | 1880 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
1839 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1881 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; |
1840 | rt->u.dst.obsolete = -1; | 1882 | rt->u.dst.obsolete = -1; |
1841 | 1883 | ||
@@ -1852,26 +1894,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1852 | 1894 | ||
1853 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1895 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
1854 | rt->rt6i_dst.plen = 128; | 1896 | rt->rt6i_dst.plen = 128; |
1855 | rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL); | 1897 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
1856 | 1898 | ||
1857 | atomic_set(&rt->u.dst.__refcnt, 1); | 1899 | atomic_set(&rt->u.dst.__refcnt, 1); |
1858 | 1900 | ||
1859 | return rt; | 1901 | return rt; |
1860 | } | 1902 | } |
1861 | 1903 | ||
1904 | struct arg_dev_net { | ||
1905 | struct net_device *dev; | ||
1906 | struct net *net; | ||
1907 | }; | ||
1908 | |||
1862 | static int fib6_ifdown(struct rt6_info *rt, void *arg) | 1909 | static int fib6_ifdown(struct rt6_info *rt, void *arg) |
1863 | { | 1910 | { |
1864 | if (((void*)rt->rt6i_dev == arg || arg == NULL) && | 1911 | struct net_device *dev = ((struct arg_dev_net *)arg)->dev; |
1865 | rt != &ip6_null_entry) { | 1912 | struct net *net = ((struct arg_dev_net *)arg)->net; |
1913 | |||
1914 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | ||
1915 | rt != net->ipv6.ip6_null_entry) { | ||
1866 | RT6_TRACE("deleted by ifdown %p\n", rt); | 1916 | RT6_TRACE("deleted by ifdown %p\n", rt); |
1867 | return -1; | 1917 | return -1; |
1868 | } | 1918 | } |
1869 | return 0; | 1919 | return 0; |
1870 | } | 1920 | } |
1871 | 1921 | ||
1872 | void rt6_ifdown(struct net_device *dev) | 1922 | void rt6_ifdown(struct net *net, struct net_device *dev) |
1873 | { | 1923 | { |
1874 | fib6_clean_all(fib6_ifdown, 0, dev); | 1924 | struct arg_dev_net adn = { |
1925 | .dev = dev, | ||
1926 | .net = net, | ||
1927 | }; | ||
1928 | |||
1929 | fib6_clean_all(net, fib6_ifdown, 0, &adn); | ||
1875 | } | 1930 | } |
1876 | 1931 | ||
1877 | struct rt6_mtu_change_arg | 1932 | struct rt6_mtu_change_arg |
@@ -1884,6 +1939,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
1884 | { | 1939 | { |
1885 | struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; | 1940 | struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; |
1886 | struct inet6_dev *idev; | 1941 | struct inet6_dev *idev; |
1942 | struct net *net = dev_net(arg->dev); | ||
1887 | 1943 | ||
1888 | /* In IPv6 pmtu discovery is not optional, | 1944 | /* In IPv6 pmtu discovery is not optional, |
1889 | so that RTAX_MTU lock cannot disable it. | 1945 | so that RTAX_MTU lock cannot disable it. |
@@ -1915,7 +1971,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
1915 | (dst_mtu(&rt->u.dst) < arg->mtu && | 1971 | (dst_mtu(&rt->u.dst) < arg->mtu && |
1916 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { | 1972 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { |
1917 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; | 1973 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; |
1918 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu); | 1974 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); |
1919 | } | 1975 | } |
1920 | return 0; | 1976 | return 0; |
1921 | } | 1977 | } |
@@ -1927,7 +1983,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu) | |||
1927 | .mtu = mtu, | 1983 | .mtu = mtu, |
1928 | }; | 1984 | }; |
1929 | 1985 | ||
1930 | fib6_clean_all(rt6_mtu_change_route, 0, &arg); | 1986 | fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg); |
1931 | } | 1987 | } |
1932 | 1988 | ||
1933 | static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { | 1989 | static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { |
@@ -1964,7 +2020,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1964 | 2020 | ||
1965 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; | 2021 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; |
1966 | cfg->fc_nlinfo.nlh = nlh; | 2022 | cfg->fc_nlinfo.nlh = nlh; |
1967 | cfg->fc_nlinfo.nl_net = skb->sk->sk_net; | 2023 | cfg->fc_nlinfo.nl_net = sock_net(skb->sk); |
1968 | 2024 | ||
1969 | if (tb[RTA_GATEWAY]) { | 2025 | if (tb[RTA_GATEWAY]) { |
1970 | nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16); | 2026 | nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16); |
@@ -2010,13 +2066,9 @@ errout: | |||
2010 | 2066 | ||
2011 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2067 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2012 | { | 2068 | { |
2013 | struct net *net = skb->sk->sk_net; | ||
2014 | struct fib6_config cfg; | 2069 | struct fib6_config cfg; |
2015 | int err; | 2070 | int err; |
2016 | 2071 | ||
2017 | if (net != &init_net) | ||
2018 | return -EINVAL; | ||
2019 | |||
2020 | err = rtm_to_fib6_config(skb, nlh, &cfg); | 2072 | err = rtm_to_fib6_config(skb, nlh, &cfg); |
2021 | if (err < 0) | 2073 | if (err < 0) |
2022 | return err; | 2074 | return err; |
@@ -2026,13 +2078,9 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a | |||
2026 | 2078 | ||
2027 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2079 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2028 | { | 2080 | { |
2029 | struct net *net = skb->sk->sk_net; | ||
2030 | struct fib6_config cfg; | 2081 | struct fib6_config cfg; |
2031 | int err; | 2082 | int err; |
2032 | 2083 | ||
2033 | if (net != &init_net) | ||
2034 | return -EINVAL; | ||
2035 | |||
2036 | err = rtm_to_fib6_config(skb, nlh, &cfg); | 2084 | err = rtm_to_fib6_config(skb, nlh, &cfg); |
2037 | if (err < 0) | 2085 | if (err < 0) |
2038 | return err; | 2086 | return err; |
@@ -2122,7 +2170,8 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2122 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2170 | NLA_PUT_U32(skb, RTA_IIF, iif); |
2123 | else if (dst) { | 2171 | else if (dst) { |
2124 | struct in6_addr saddr_buf; | 2172 | struct in6_addr saddr_buf; |
2125 | if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) | 2173 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, |
2174 | dst, 0, &saddr_buf) == 0) | ||
2126 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2175 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2127 | } | 2176 | } |
2128 | 2177 | ||
@@ -2167,7 +2216,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2167 | 2216 | ||
2168 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | 2217 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) |
2169 | { | 2218 | { |
2170 | struct net *net = in_skb->sk->sk_net; | 2219 | struct net *net = sock_net(in_skb->sk); |
2171 | struct nlattr *tb[RTA_MAX+1]; | 2220 | struct nlattr *tb[RTA_MAX+1]; |
2172 | struct rt6_info *rt; | 2221 | struct rt6_info *rt; |
2173 | struct sk_buff *skb; | 2222 | struct sk_buff *skb; |
@@ -2175,9 +2224,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2175 | struct flowi fl; | 2224 | struct flowi fl; |
2176 | int err, iif = 0; | 2225 | int err, iif = 0; |
2177 | 2226 | ||
2178 | if (net != &init_net) | ||
2179 | return -EINVAL; | ||
2180 | |||
2181 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); | 2227 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); |
2182 | if (err < 0) | 2228 | if (err < 0) |
2183 | goto errout; | 2229 | goto errout; |
@@ -2207,7 +2253,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2207 | 2253 | ||
2208 | if (iif) { | 2254 | if (iif) { |
2209 | struct net_device *dev; | 2255 | struct net_device *dev; |
2210 | dev = __dev_get_by_index(&init_net, iif); | 2256 | dev = __dev_get_by_index(net, iif); |
2211 | if (!dev) { | 2257 | if (!dev) { |
2212 | err = -ENODEV; | 2258 | err = -ENODEV; |
2213 | goto errout; | 2259 | goto errout; |
@@ -2226,7 +2272,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2226 | skb_reset_mac_header(skb); | 2272 | skb_reset_mac_header(skb); |
2227 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2273 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2228 | 2274 | ||
2229 | rt = (struct rt6_info*) ip6_route_output(NULL, &fl); | 2275 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); |
2230 | skb->dst = &rt->u.dst; | 2276 | skb->dst = &rt->u.dst; |
2231 | 2277 | ||
2232 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2278 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
@@ -2237,7 +2283,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2237 | goto errout; | 2283 | goto errout; |
2238 | } | 2284 | } |
2239 | 2285 | ||
2240 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 2286 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
2241 | errout: | 2287 | errout: |
2242 | return err; | 2288 | return err; |
2243 | } | 2289 | } |
@@ -2245,6 +2291,7 @@ errout: | |||
2245 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | 2291 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) |
2246 | { | 2292 | { |
2247 | struct sk_buff *skb; | 2293 | struct sk_buff *skb; |
2294 | struct net *net = info->nl_net; | ||
2248 | u32 seq; | 2295 | u32 seq; |
2249 | int err; | 2296 | int err; |
2250 | 2297 | ||
@@ -2263,11 +2310,31 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2263 | kfree_skb(skb); | 2310 | kfree_skb(skb); |
2264 | goto errout; | 2311 | goto errout; |
2265 | } | 2312 | } |
2266 | err = rtnl_notify(skb, &init_net, info->pid, | 2313 | err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, |
2267 | RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any()); | 2314 | info->nlh, gfp_any()); |
2268 | errout: | 2315 | errout: |
2269 | if (err < 0) | 2316 | if (err < 0) |
2270 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err); | 2317 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
2318 | } | ||
2319 | |||
2320 | static int ip6_route_dev_notify(struct notifier_block *this, | ||
2321 | unsigned long event, void *data) | ||
2322 | { | ||
2323 | struct net_device *dev = (struct net_device *)data; | ||
2324 | struct net *net = dev_net(dev); | ||
2325 | |||
2326 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | ||
2327 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | ||
2328 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | ||
2329 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2330 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | ||
2331 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | ||
2332 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | ||
2333 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | ||
2334 | #endif | ||
2335 | } | ||
2336 | |||
2337 | return NOTIFY_OK; | ||
2271 | } | 2338 | } |
2272 | 2339 | ||
2273 | /* | 2340 | /* |
@@ -2316,13 +2383,33 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2316 | 2383 | ||
2317 | static int ipv6_route_show(struct seq_file *m, void *v) | 2384 | static int ipv6_route_show(struct seq_file *m, void *v) |
2318 | { | 2385 | { |
2319 | fib6_clean_all(rt6_info_route, 0, m); | 2386 | struct net *net = (struct net *)m->private; |
2387 | fib6_clean_all(net, rt6_info_route, 0, m); | ||
2320 | return 0; | 2388 | return 0; |
2321 | } | 2389 | } |
2322 | 2390 | ||
2323 | static int ipv6_route_open(struct inode *inode, struct file *file) | 2391 | static int ipv6_route_open(struct inode *inode, struct file *file) |
2324 | { | 2392 | { |
2325 | return single_open(file, ipv6_route_show, NULL); | 2393 | int err; |
2394 | struct net *net = get_proc_net(inode); | ||
2395 | if (!net) | ||
2396 | return -ENXIO; | ||
2397 | |||
2398 | err = single_open(file, ipv6_route_show, net); | ||
2399 | if (err < 0) { | ||
2400 | put_net(net); | ||
2401 | return err; | ||
2402 | } | ||
2403 | |||
2404 | return 0; | ||
2405 | } | ||
2406 | |||
2407 | static int ipv6_route_release(struct inode *inode, struct file *file) | ||
2408 | { | ||
2409 | struct seq_file *seq = file->private_data; | ||
2410 | struct net *net = seq->private; | ||
2411 | put_net(net); | ||
2412 | return single_release(inode, file); | ||
2326 | } | 2413 | } |
2327 | 2414 | ||
2328 | static const struct file_operations ipv6_route_proc_fops = { | 2415 | static const struct file_operations ipv6_route_proc_fops = { |
@@ -2330,24 +2417,46 @@ static const struct file_operations ipv6_route_proc_fops = { | |||
2330 | .open = ipv6_route_open, | 2417 | .open = ipv6_route_open, |
2331 | .read = seq_read, | 2418 | .read = seq_read, |
2332 | .llseek = seq_lseek, | 2419 | .llseek = seq_lseek, |
2333 | .release = single_release, | 2420 | .release = ipv6_route_release, |
2334 | }; | 2421 | }; |
2335 | 2422 | ||
2336 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) | 2423 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) |
2337 | { | 2424 | { |
2425 | struct net *net = (struct net *)seq->private; | ||
2338 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", | 2426 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", |
2339 | rt6_stats.fib_nodes, rt6_stats.fib_route_nodes, | 2427 | net->ipv6.rt6_stats->fib_nodes, |
2340 | rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries, | 2428 | net->ipv6.rt6_stats->fib_route_nodes, |
2341 | rt6_stats.fib_rt_cache, | 2429 | net->ipv6.rt6_stats->fib_rt_alloc, |
2342 | atomic_read(&ip6_dst_ops.entries), | 2430 | net->ipv6.rt6_stats->fib_rt_entries, |
2343 | rt6_stats.fib_discarded_routes); | 2431 | net->ipv6.rt6_stats->fib_rt_cache, |
2432 | atomic_read(&net->ipv6.ip6_dst_ops->entries), | ||
2433 | net->ipv6.rt6_stats->fib_discarded_routes); | ||
2344 | 2434 | ||
2345 | return 0; | 2435 | return 0; |
2346 | } | 2436 | } |
2347 | 2437 | ||
2348 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) | 2438 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) |
2349 | { | 2439 | { |
2350 | return single_open(file, rt6_stats_seq_show, NULL); | 2440 | int err; |
2441 | struct net *net = get_proc_net(inode); | ||
2442 | if (!net) | ||
2443 | return -ENXIO; | ||
2444 | |||
2445 | err = single_open(file, rt6_stats_seq_show, net); | ||
2446 | if (err < 0) { | ||
2447 | put_net(net); | ||
2448 | return err; | ||
2449 | } | ||
2450 | |||
2451 | return 0; | ||
2452 | } | ||
2453 | |||
2454 | static int rt6_stats_seq_release(struct inode *inode, struct file *file) | ||
2455 | { | ||
2456 | struct seq_file *seq = file->private_data; | ||
2457 | struct net *net = (struct net *)seq->private; | ||
2458 | put_net(net); | ||
2459 | return single_release(inode, file); | ||
2351 | } | 2460 | } |
2352 | 2461 | ||
2353 | static const struct file_operations rt6_stats_seq_fops = { | 2462 | static const struct file_operations rt6_stats_seq_fops = { |
@@ -2355,42 +2464,8 @@ static const struct file_operations rt6_stats_seq_fops = { | |||
2355 | .open = rt6_stats_seq_open, | 2464 | .open = rt6_stats_seq_open, |
2356 | .read = seq_read, | 2465 | .read = seq_read, |
2357 | .llseek = seq_lseek, | 2466 | .llseek = seq_lseek, |
2358 | .release = single_release, | 2467 | .release = rt6_stats_seq_release, |
2359 | }; | 2468 | }; |
2360 | |||
2361 | static int ipv6_route_proc_init(struct net *net) | ||
2362 | { | ||
2363 | int ret = -ENOMEM; | ||
2364 | if (!proc_net_fops_create(net, "ipv6_route", | ||
2365 | 0, &ipv6_route_proc_fops)) | ||
2366 | goto out; | ||
2367 | |||
2368 | if (!proc_net_fops_create(net, "rt6_stats", | ||
2369 | S_IRUGO, &rt6_stats_seq_fops)) | ||
2370 | goto out_ipv6_route; | ||
2371 | |||
2372 | ret = 0; | ||
2373 | out: | ||
2374 | return ret; | ||
2375 | out_ipv6_route: | ||
2376 | proc_net_remove(net, "ipv6_route"); | ||
2377 | goto out; | ||
2378 | } | ||
2379 | |||
2380 | static void ipv6_route_proc_fini(struct net *net) | ||
2381 | { | ||
2382 | proc_net_remove(net, "ipv6_route"); | ||
2383 | proc_net_remove(net, "rt6_stats"); | ||
2384 | } | ||
2385 | #else | ||
2386 | static inline int ipv6_route_proc_init(struct net *net) | ||
2387 | { | ||
2388 | return 0; | ||
2389 | } | ||
2390 | static inline void ipv6_route_proc_fini(struct net *net) | ||
2391 | { | ||
2392 | return ; | ||
2393 | } | ||
2394 | #endif /* CONFIG_PROC_FS */ | 2469 | #endif /* CONFIG_PROC_FS */ |
2395 | 2470 | ||
2396 | #ifdef CONFIG_SYSCTL | 2471 | #ifdef CONFIG_SYSCTL |
@@ -2399,10 +2474,11 @@ static | |||
2399 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, | 2474 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, |
2400 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2475 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2401 | { | 2476 | { |
2402 | int delay = init_net.ipv6.sysctl.flush_delay; | 2477 | struct net *net = current->nsproxy->net_ns; |
2478 | int delay = net->ipv6.sysctl.flush_delay; | ||
2403 | if (write) { | 2479 | if (write) { |
2404 | proc_dointvec(ctl, write, filp, buffer, lenp, ppos); | 2480 | proc_dointvec(ctl, write, filp, buffer, lenp, ppos); |
2405 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay); | 2481 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net); |
2406 | return 0; | 2482 | return 0; |
2407 | } else | 2483 | } else |
2408 | return -EINVAL; | 2484 | return -EINVAL; |
@@ -2419,7 +2495,7 @@ ctl_table ipv6_route_table_template[] = { | |||
2419 | { | 2495 | { |
2420 | .ctl_name = NET_IPV6_ROUTE_GC_THRESH, | 2496 | .ctl_name = NET_IPV6_ROUTE_GC_THRESH, |
2421 | .procname = "gc_thresh", | 2497 | .procname = "gc_thresh", |
2422 | .data = &ip6_dst_ops.gc_thresh, | 2498 | .data = &ip6_dst_ops_template.gc_thresh, |
2423 | .maxlen = sizeof(int), | 2499 | .maxlen = sizeof(int), |
2424 | .mode = 0644, | 2500 | .mode = 0644, |
2425 | .proc_handler = &proc_dointvec, | 2501 | .proc_handler = &proc_dointvec, |
@@ -2505,33 +2581,141 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) | |||
2505 | table = kmemdup(ipv6_route_table_template, | 2581 | table = kmemdup(ipv6_route_table_template, |
2506 | sizeof(ipv6_route_table_template), | 2582 | sizeof(ipv6_route_table_template), |
2507 | GFP_KERNEL); | 2583 | GFP_KERNEL); |
2584 | |||
2585 | if (table) { | ||
2586 | table[0].data = &net->ipv6.sysctl.flush_delay; | ||
2587 | table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh; | ||
2588 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; | ||
2589 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | ||
2590 | table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
2591 | table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval; | ||
2592 | table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
2593 | table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; | ||
2594 | table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; | ||
2595 | } | ||
2596 | |||
2508 | return table; | 2597 | return table; |
2509 | } | 2598 | } |
2510 | #endif | 2599 | #endif |
2511 | 2600 | ||
2601 | static int ip6_route_net_init(struct net *net) | ||
2602 | { | ||
2603 | int ret = 0; | ||
2604 | |||
2605 | ret = -ENOMEM; | ||
2606 | net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template, | ||
2607 | sizeof(*net->ipv6.ip6_dst_ops), | ||
2608 | GFP_KERNEL); | ||
2609 | if (!net->ipv6.ip6_dst_ops) | ||
2610 | goto out; | ||
2611 | net->ipv6.ip6_dst_ops->dst_net = net; | ||
2612 | |||
2613 | net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, | ||
2614 | sizeof(*net->ipv6.ip6_null_entry), | ||
2615 | GFP_KERNEL); | ||
2616 | if (!net->ipv6.ip6_null_entry) | ||
2617 | goto out_ip6_dst_ops; | ||
2618 | net->ipv6.ip6_null_entry->u.dst.path = | ||
2619 | (struct dst_entry *)net->ipv6.ip6_null_entry; | ||
2620 | net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2621 | |||
2622 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2623 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | ||
2624 | sizeof(*net->ipv6.ip6_prohibit_entry), | ||
2625 | GFP_KERNEL); | ||
2626 | if (!net->ipv6.ip6_prohibit_entry) { | ||
2627 | kfree(net->ipv6.ip6_null_entry); | ||
2628 | goto out; | ||
2629 | } | ||
2630 | net->ipv6.ip6_prohibit_entry->u.dst.path = | ||
2631 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | ||
2632 | net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2633 | |||
2634 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | ||
2635 | sizeof(*net->ipv6.ip6_blk_hole_entry), | ||
2636 | GFP_KERNEL); | ||
2637 | if (!net->ipv6.ip6_blk_hole_entry) { | ||
2638 | kfree(net->ipv6.ip6_null_entry); | ||
2639 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2640 | goto out; | ||
2641 | } | ||
2642 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | ||
2643 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | ||
2644 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2645 | #endif | ||
2646 | |||
2647 | #ifdef CONFIG_PROC_FS | ||
2648 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2649 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2650 | #endif | ||
2651 | net->ipv6.ip6_rt_gc_expire = 30*HZ; | ||
2652 | |||
2653 | ret = 0; | ||
2654 | out: | ||
2655 | return ret; | ||
2656 | |||
2657 | out_ip6_dst_ops: | ||
2658 | kfree(net->ipv6.ip6_dst_ops); | ||
2659 | goto out; | ||
2660 | } | ||
2661 | |||
2662 | static void ip6_route_net_exit(struct net *net) | ||
2663 | { | ||
2664 | #ifdef CONFIG_PROC_FS | ||
2665 | proc_net_remove(net, "ipv6_route"); | ||
2666 | proc_net_remove(net, "rt6_stats"); | ||
2667 | #endif | ||
2668 | kfree(net->ipv6.ip6_null_entry); | ||
2669 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2670 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2671 | kfree(net->ipv6.ip6_blk_hole_entry); | ||
2672 | #endif | ||
2673 | kfree(net->ipv6.ip6_dst_ops); | ||
2674 | } | ||
2675 | |||
2676 | static struct pernet_operations ip6_route_net_ops = { | ||
2677 | .init = ip6_route_net_init, | ||
2678 | .exit = ip6_route_net_exit, | ||
2679 | }; | ||
2680 | |||
2681 | static struct notifier_block ip6_route_dev_notifier = { | ||
2682 | .notifier_call = ip6_route_dev_notify, | ||
2683 | .priority = 0, | ||
2684 | }; | ||
2685 | |||
2512 | int __init ip6_route_init(void) | 2686 | int __init ip6_route_init(void) |
2513 | { | 2687 | { |
2514 | int ret; | 2688 | int ret; |
2515 | 2689 | ||
2516 | ip6_dst_ops.kmem_cachep = | 2690 | ret = -ENOMEM; |
2691 | ip6_dst_ops_template.kmem_cachep = | ||
2517 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, | 2692 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, |
2518 | SLAB_HWCACHE_ALIGN, NULL); | 2693 | SLAB_HWCACHE_ALIGN, NULL); |
2519 | if (!ip6_dst_ops.kmem_cachep) | 2694 | if (!ip6_dst_ops_template.kmem_cachep) |
2520 | return -ENOMEM; | 2695 | goto out;; |
2521 | 2696 | ||
2522 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; | 2697 | ret = register_pernet_subsys(&ip6_route_net_ops); |
2523 | |||
2524 | ret = fib6_init(); | ||
2525 | if (ret) | 2698 | if (ret) |
2526 | goto out_kmem_cache; | 2699 | goto out_kmem_cache; |
2527 | 2700 | ||
2528 | ret = ipv6_route_proc_init(&init_net); | 2701 | /* Registering of the loopback is done before this portion of code, |
2702 | * the loopback reference in rt6_info will not be taken, do it | ||
2703 | * manually for init_net */ | ||
2704 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | ||
2705 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2706 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2707 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | ||
2708 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2709 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | ||
2710 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2711 | #endif | ||
2712 | ret = fib6_init(); | ||
2529 | if (ret) | 2713 | if (ret) |
2530 | goto out_fib6_init; | 2714 | goto out_register_subsys; |
2531 | 2715 | ||
2532 | ret = xfrm6_init(); | 2716 | ret = xfrm6_init(); |
2533 | if (ret) | 2717 | if (ret) |
2534 | goto out_proc_init; | 2718 | goto out_fib6_init; |
2535 | 2719 | ||
2536 | ret = fib6_rules_init(); | 2720 | ret = fib6_rules_init(); |
2537 | if (ret) | 2721 | if (ret) |
@@ -2543,7 +2727,10 @@ int __init ip6_route_init(void) | |||
2543 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2727 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) |
2544 | goto fib6_rules_init; | 2728 | goto fib6_rules_init; |
2545 | 2729 | ||
2546 | ret = 0; | 2730 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
2731 | if (ret) | ||
2732 | goto fib6_rules_init; | ||
2733 | |||
2547 | out: | 2734 | out: |
2548 | return ret; | 2735 | return ret; |
2549 | 2736 | ||
@@ -2551,22 +2738,21 @@ fib6_rules_init: | |||
2551 | fib6_rules_cleanup(); | 2738 | fib6_rules_cleanup(); |
2552 | xfrm6_init: | 2739 | xfrm6_init: |
2553 | xfrm6_fini(); | 2740 | xfrm6_fini(); |
2554 | out_proc_init: | ||
2555 | ipv6_route_proc_fini(&init_net); | ||
2556 | out_fib6_init: | 2741 | out_fib6_init: |
2557 | rt6_ifdown(NULL); | ||
2558 | fib6_gc_cleanup(); | 2742 | fib6_gc_cleanup(); |
2743 | out_register_subsys: | ||
2744 | unregister_pernet_subsys(&ip6_route_net_ops); | ||
2559 | out_kmem_cache: | 2745 | out_kmem_cache: |
2560 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2746 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); |
2561 | goto out; | 2747 | goto out; |
2562 | } | 2748 | } |
2563 | 2749 | ||
2564 | void ip6_route_cleanup(void) | 2750 | void ip6_route_cleanup(void) |
2565 | { | 2751 | { |
2752 | unregister_netdevice_notifier(&ip6_route_dev_notifier); | ||
2566 | fib6_rules_cleanup(); | 2753 | fib6_rules_cleanup(); |
2567 | ipv6_route_proc_fini(&init_net); | ||
2568 | xfrm6_fini(); | 2754 | xfrm6_fini(); |
2569 | rt6_ifdown(NULL); | ||
2570 | fib6_gc_cleanup(); | 2755 | fib6_gc_cleanup(); |
2571 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2756 | unregister_pernet_subsys(&ip6_route_net_ops); |
2757 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); | ||
2572 | } | 2758 | } |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1656c003b989..1b8196c8d145 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -339,11 +339,11 @@ out: | |||
339 | skb_reset_network_header(skb2); | 339 | skb_reset_network_header(skb2); |
340 | 340 | ||
341 | /* Try to guess incoming interface */ | 341 | /* Try to guess incoming interface */ |
342 | rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); | 342 | rt6i = rt6_lookup(&init_net, &iph6->saddr, NULL, NULL, 0); |
343 | if (rt6i && rt6i->rt6i_dev) { | 343 | if (rt6i && rt6i->rt6i_dev) { |
344 | skb2->dev = rt6i->rt6i_dev; | 344 | skb2->dev = rt6i->rt6i_dev; |
345 | 345 | ||
346 | rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); | 346 | rt6i = rt6_lookup(&init_net, &iph6->daddr, &iph6->saddr, NULL, 0); |
347 | 347 | ||
348 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { | 348 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { |
349 | struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); | 349 | struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); |
@@ -393,7 +393,7 @@ isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev) | |||
393 | fl.oif = dev->ifindex; | 393 | fl.oif = dev->ifindex; |
394 | security_skb_classify_flow(skb, &fl); | 394 | security_skb_classify_flow(skb, &fl); |
395 | 395 | ||
396 | dst = ip6_route_output(NULL, &fl); | 396 | dst = ip6_route_output(&init_net, NULL, &fl); |
397 | if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) { | 397 | if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) { |
398 | 398 | ||
399 | addr6 = (struct in6_addr*)&neigh->primary_key; | 399 | addr6 = (struct in6_addr*)&neigh->primary_key; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c new file mode 100644 index 000000000000..3a622e7abc02 --- /dev/null +++ b/net/ipv6/syncookies.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * IPv6 Syncookies implementation for the Linux kernel | ||
3 | * | ||
4 | * Authors: | ||
5 | * Glenn Griffin <ggriffin.kernel@gmail.com> | ||
6 | * | ||
7 | * Based on IPv4 implementation by Andi Kleen | ||
8 | * linux/net/ipv4/syncookies.c | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/tcp.h> | ||
18 | #include <linux/random.h> | ||
19 | #include <linux/cryptohash.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <net/ipv6.h> | ||
22 | #include <net/tcp.h> | ||
23 | |||
24 | extern int sysctl_tcp_syncookies; | ||
25 | extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | ||
26 | |||
27 | #define COOKIEBITS 24 /* Upper bits store count */ | ||
28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | ||
29 | |||
30 | /* | ||
31 | * This table has to be sorted and terminated with (__u16)-1. | ||
32 | * XXX generate a better table. | ||
33 | * Unresolved Issues: HIPPI with a 64k MSS is not well supported. | ||
34 | * | ||
35 | * Taken directly from ipv4 implementation. | ||
36 | * Should this list be modified for ipv6 use or is it close enough? | ||
37 | * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart | ||
38 | */ | ||
39 | static __u16 const msstab[] = { | ||
40 | 64 - 1, | ||
41 | 256 - 1, | ||
42 | 512 - 1, | ||
43 | 536 - 1, | ||
44 | 1024 - 1, | ||
45 | 1440 - 1, | ||
46 | 1460 - 1, | ||
47 | 4312 - 1, | ||
48 | (__u16)-1 | ||
49 | }; | ||
50 | /* The number doesn't include the -1 terminator */ | ||
51 | #define NUM_MSS (ARRAY_SIZE(msstab) - 1) | ||
52 | |||
53 | /* | ||
54 | * This (misnamed) value is the age of syncookie which is permitted. | ||
55 | * Its ideal value should be dependent on TCP_TIMEOUT_INIT and | ||
56 | * sysctl_tcp_retries1. It's a rather complicated formula (exponential | ||
57 | * backoff) to compute at runtime so it's currently hardcoded here. | ||
58 | */ | ||
59 | #define COUNTER_TRIES 4 | ||
60 | |||
61 | static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | ||
62 | struct request_sock *req, | ||
63 | struct dst_entry *dst) | ||
64 | { | ||
65 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
66 | struct sock *child; | ||
67 | |||
68 | child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst); | ||
69 | if (child) | ||
70 | inet_csk_reqsk_queue_add(sk, req, child); | ||
71 | else | ||
72 | reqsk_free(req); | ||
73 | |||
74 | return child; | ||
75 | } | ||
76 | |||
77 | static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS]; | ||
78 | |||
79 | static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr, | ||
80 | __be16 sport, __be16 dport, u32 count, int c) | ||
81 | { | ||
82 | __u32 *tmp = __get_cpu_var(cookie_scratch); | ||
83 | |||
84 | /* | ||
85 | * we have 320 bits of information to hash, copy in the remaining | ||
86 | * 192 bits required for sha_transform, from the syncookie_secret | ||
87 | * and overwrite the digest with the secret | ||
88 | */ | ||
89 | memcpy(tmp + 10, syncookie_secret[c], 44); | ||
90 | memcpy(tmp, saddr, 16); | ||
91 | memcpy(tmp + 4, daddr, 16); | ||
92 | tmp[8] = ((__force u32)sport << 16) + (__force u32)dport; | ||
93 | tmp[9] = count; | ||
94 | sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); | ||
95 | |||
96 | return tmp[17]; | ||
97 | } | ||
98 | |||
99 | static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *daddr, | ||
100 | __be16 sport, __be16 dport, __u32 sseq, | ||
101 | __u32 count, __u32 data) | ||
102 | { | ||
103 | return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + | ||
104 | sseq + (count << COOKIEBITS) + | ||
105 | ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) | ||
106 | & COOKIEMASK)); | ||
107 | } | ||
108 | |||
109 | static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr, | ||
110 | struct in6_addr *daddr, __be16 sport, | ||
111 | __be16 dport, __u32 sseq, __u32 count, | ||
112 | __u32 maxdiff) | ||
113 | { | ||
114 | __u32 diff; | ||
115 | |||
116 | cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; | ||
117 | |||
118 | diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS); | ||
119 | if (diff >= maxdiff) | ||
120 | return (__u32)-1; | ||
121 | |||
122 | return (cookie - | ||
123 | cookie_hash(saddr, daddr, sport, dport, count - diff, 1)) | ||
124 | & COOKIEMASK; | ||
125 | } | ||
126 | |||
127 | __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | ||
128 | { | ||
129 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
130 | const struct tcphdr *th = tcp_hdr(skb); | ||
131 | int mssind; | ||
132 | const __u16 mss = *mssp; | ||
133 | |||
134 | tcp_sk(sk)->last_synq_overflow = jiffies; | ||
135 | |||
136 | for (mssind = 0; mss > msstab[mssind + 1]; mssind++) | ||
137 | ; | ||
138 | *mssp = msstab[mssind] + 1; | ||
139 | |||
140 | NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESSENT); | ||
141 | |||
142 | return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source, | ||
143 | th->dest, ntohl(th->seq), | ||
144 | jiffies / (HZ * 60), mssind); | ||
145 | } | ||
146 | |||
147 | static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | ||
148 | { | ||
149 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
150 | const struct tcphdr *th = tcp_hdr(skb); | ||
151 | __u32 seq = ntohl(th->seq) - 1; | ||
152 | __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, | ||
153 | th->source, th->dest, seq, | ||
154 | jiffies / (HZ * 60), COUNTER_TRIES); | ||
155 | |||
156 | return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; | ||
157 | } | ||
158 | |||
159 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | ||
160 | { | ||
161 | struct inet_request_sock *ireq; | ||
162 | struct inet6_request_sock *ireq6; | ||
163 | struct tcp_request_sock *treq; | ||
164 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
165 | struct tcp_sock *tp = tcp_sk(sk); | ||
166 | const struct tcphdr *th = tcp_hdr(skb); | ||
167 | __u32 cookie = ntohl(th->ack_seq) - 1; | ||
168 | struct sock *ret = sk; | ||
169 | struct request_sock *req; | ||
170 | int mss; | ||
171 | struct dst_entry *dst; | ||
172 | __u8 rcv_wscale; | ||
173 | |||
174 | if (!sysctl_tcp_syncookies || !th->ack) | ||
175 | goto out; | ||
176 | |||
177 | if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || | ||
178 | (mss = cookie_check(skb, cookie)) == 0) { | ||
179 | NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED); | ||
180 | goto out; | ||
181 | } | ||
182 | |||
183 | NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); | ||
184 | |||
185 | ret = NULL; | ||
186 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | ||
187 | if (!req) | ||
188 | goto out; | ||
189 | |||
190 | ireq = inet_rsk(req); | ||
191 | ireq6 = inet6_rsk(req); | ||
192 | treq = tcp_rsk(req); | ||
193 | ireq6->pktopts = NULL; | ||
194 | |||
195 | if (security_inet_conn_request(sk, skb, req)) { | ||
196 | reqsk_free(req); | ||
197 | goto out; | ||
198 | } | ||
199 | |||
200 | req->mss = mss; | ||
201 | ireq->rmt_port = th->source; | ||
202 | ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr); | ||
203 | ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr); | ||
204 | if (ipv6_opt_accepted(sk, skb) || | ||
205 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
206 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | ||
207 | atomic_inc(&skb->users); | ||
208 | ireq6->pktopts = skb; | ||
209 | } | ||
210 | |||
211 | ireq6->iif = sk->sk_bound_dev_if; | ||
212 | /* So that link locals have meaning */ | ||
213 | if (!sk->sk_bound_dev_if && | ||
214 | ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL) | ||
215 | ireq6->iif = inet6_iif(skb); | ||
216 | |||
217 | req->expires = 0UL; | ||
218 | req->retrans = 0; | ||
219 | ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0; | ||
220 | ireq->wscale_ok = ireq->sack_ok = 0; | ||
221 | treq->rcv_isn = ntohl(th->seq) - 1; | ||
222 | treq->snt_isn = cookie; | ||
223 | |||
224 | /* | ||
225 | * We need to lookup the dst_entry to get the correct window size. | ||
226 | * This is taken from tcp_v6_syn_recv_sock. Somebody please enlighten | ||
227 | * me if there is a preferred way. | ||
228 | */ | ||
229 | { | ||
230 | struct in6_addr *final_p = NULL, final; | ||
231 | struct flowi fl; | ||
232 | memset(&fl, 0, sizeof(fl)); | ||
233 | fl.proto = IPPROTO_TCP; | ||
234 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | ||
235 | if (np->opt && np->opt->srcrt) { | ||
236 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
237 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
238 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
239 | final_p = &final; | ||
240 | } | ||
241 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | ||
242 | fl.oif = sk->sk_bound_dev_if; | ||
243 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | ||
244 | fl.fl_ip_sport = inet_sk(sk)->sport; | ||
245 | security_req_classify_flow(req, &fl); | ||
246 | if (ip6_dst_lookup(sk, &dst, &fl)) { | ||
247 | reqsk_free(req); | ||
248 | goto out; | ||
249 | } | ||
250 | if (final_p) | ||
251 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
252 | if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
253 | goto out; | ||
254 | } | ||
255 | |||
256 | req->window_clamp = dst_metric(dst, RTAX_WINDOW); | ||
257 | tcp_select_initial_window(tcp_full_space(sk), req->mss, | ||
258 | &req->rcv_wnd, &req->window_clamp, | ||
259 | 0, &rcv_wscale); | ||
260 | |||
261 | ireq->rcv_wscale = rcv_wscale; | ||
262 | |||
263 | ret = get_cookie_sock(sk, skb, req, dst); | ||
264 | |||
265 | out: return ret; | ||
266 | } | ||
267 | |||
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index d6d3e68086f8..3804dcbbfab0 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -71,24 +71,11 @@ static int ipv6_sysctl_net_init(struct net *net) | |||
71 | ipv6_route_table = ipv6_route_sysctl_init(net); | 71 | ipv6_route_table = ipv6_route_sysctl_init(net); |
72 | if (!ipv6_route_table) | 72 | if (!ipv6_route_table) |
73 | goto out_ipv6_table; | 73 | goto out_ipv6_table; |
74 | ipv6_table[0].child = ipv6_route_table; | ||
74 | 75 | ||
75 | ipv6_icmp_table = ipv6_icmp_sysctl_init(net); | 76 | ipv6_icmp_table = ipv6_icmp_sysctl_init(net); |
76 | if (!ipv6_icmp_table) | 77 | if (!ipv6_icmp_table) |
77 | goto out_ipv6_route_table; | 78 | goto out_ipv6_route_table; |
78 | |||
79 | ipv6_route_table[0].data = &net->ipv6.sysctl.flush_delay; | ||
80 | /* ipv6_route_table[1].data will be handled when we have | ||
81 | routes per namespace */ | ||
82 | ipv6_route_table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; | ||
83 | ipv6_route_table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | ||
84 | ipv6_route_table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
85 | ipv6_route_table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval; | ||
86 | ipv6_route_table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
87 | ipv6_route_table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; | ||
88 | ipv6_route_table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; | ||
89 | ipv6_table[0].child = ipv6_route_table; | ||
90 | |||
91 | ipv6_icmp_table[0].data = &net->ipv6.sysctl.icmpv6_time; | ||
92 | ipv6_table[1].child = ipv6_icmp_table; | 79 | ipv6_table[1].child = ipv6_icmp_table; |
93 | 80 | ||
94 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; | 81 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 12750f2b05ab..323c7e06ef43 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -69,9 +69,6 @@ | |||
69 | #include <linux/crypto.h> | 69 | #include <linux/crypto.h> |
70 | #include <linux/scatterlist.h> | 70 | #include <linux/scatterlist.h> |
71 | 71 | ||
72 | /* Socket used for sending RSTs and ACKs */ | ||
73 | static struct socket *tcp6_socket; | ||
74 | |||
75 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); | 72 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); |
76 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); | 73 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); |
77 | static void tcp_v6_send_check(struct sock *sk, int len, | 74 | static void tcp_v6_send_check(struct sock *sk, int len, |
@@ -324,7 +321,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
324 | struct tcp_sock *tp; | 321 | struct tcp_sock *tp; |
325 | __u32 seq; | 322 | __u32 seq; |
326 | 323 | ||
327 | sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr, | 324 | sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr, |
328 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 325 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); |
329 | 326 | ||
330 | if (sk == NULL) { | 327 | if (sk == NULL) { |
@@ -455,8 +452,7 @@ out: | |||
455 | } | 452 | } |
456 | 453 | ||
457 | 454 | ||
458 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | 455 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) |
459 | struct dst_entry *dst) | ||
460 | { | 456 | { |
461 | struct inet6_request_sock *treq = inet6_rsk(req); | 457 | struct inet6_request_sock *treq = inet6_rsk(req); |
462 | struct ipv6_pinfo *np = inet6_sk(sk); | 458 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -464,6 +460,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
464 | struct ipv6_txoptions *opt = NULL; | 460 | struct ipv6_txoptions *opt = NULL; |
465 | struct in6_addr * final_p = NULL, final; | 461 | struct in6_addr * final_p = NULL, final; |
466 | struct flowi fl; | 462 | struct flowi fl; |
463 | struct dst_entry *dst; | ||
467 | int err = -1; | 464 | int err = -1; |
468 | 465 | ||
469 | memset(&fl, 0, sizeof(fl)); | 466 | memset(&fl, 0, sizeof(fl)); |
@@ -476,24 +473,22 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
476 | fl.fl_ip_sport = inet_sk(sk)->sport; | 473 | fl.fl_ip_sport = inet_sk(sk)->sport; |
477 | security_req_classify_flow(req, &fl); | 474 | security_req_classify_flow(req, &fl); |
478 | 475 | ||
479 | if (dst == NULL) { | 476 | opt = np->opt; |
480 | opt = np->opt; | 477 | if (opt && opt->srcrt) { |
481 | if (opt && opt->srcrt) { | 478 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
482 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 479 | ipv6_addr_copy(&final, &fl.fl6_dst); |
483 | ipv6_addr_copy(&final, &fl.fl6_dst); | 480 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
484 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | 481 | final_p = &final; |
485 | final_p = &final; | ||
486 | } | ||
487 | |||
488 | err = ip6_dst_lookup(sk, &dst, &fl); | ||
489 | if (err) | ||
490 | goto done; | ||
491 | if (final_p) | ||
492 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
493 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
494 | goto done; | ||
495 | } | 482 | } |
496 | 483 | ||
484 | err = ip6_dst_lookup(sk, &dst, &fl); | ||
485 | if (err) | ||
486 | goto done; | ||
487 | if (final_p) | ||
488 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
489 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
490 | goto done; | ||
491 | |||
497 | skb = tcp_make_synack(sk, dst, req); | 492 | skb = tcp_make_synack(sk, dst, req); |
498 | if (skb) { | 493 | if (skb) { |
499 | struct tcphdr *th = tcp_hdr(skb); | 494 | struct tcphdr *th = tcp_hdr(skb); |
@@ -514,6 +509,20 @@ done: | |||
514 | return err; | 509 | return err; |
515 | } | 510 | } |
516 | 511 | ||
512 | static inline void syn_flood_warning(struct sk_buff *skb) | ||
513 | { | ||
514 | #ifdef CONFIG_SYN_COOKIES | ||
515 | if (sysctl_tcp_syncookies) | ||
516 | printk(KERN_INFO | ||
517 | "TCPv6: Possible SYN flooding on port %d. " | ||
518 | "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest)); | ||
519 | else | ||
520 | #endif | ||
521 | printk(KERN_INFO | ||
522 | "TCPv6: Possible SYN flooding on port %d. " | ||
523 | "Dropping request.\n", ntohs(tcp_hdr(skb)->dest)); | ||
524 | } | ||
525 | |||
517 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 526 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
518 | { | 527 | { |
519 | if (inet6_rsk(req)->pktopts) | 528 | if (inet6_rsk(req)->pktopts) |
@@ -741,7 +750,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
741 | 750 | ||
742 | hp = tcp_get_md5sig_pool(); | 751 | hp = tcp_get_md5sig_pool(); |
743 | if (!hp) { | 752 | if (!hp) { |
744 | printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__); | 753 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); |
745 | goto clear_hash_noput; | 754 | goto clear_hash_noput; |
746 | } | 755 | } |
747 | bp = &hp->md5_blk.ip6; | 756 | bp = &hp->md5_blk.ip6; |
@@ -781,17 +790,17 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
781 | /* Now store the hash into the packet */ | 790 | /* Now store the hash into the packet */ |
782 | err = crypto_hash_init(desc); | 791 | err = crypto_hash_init(desc); |
783 | if (err) { | 792 | if (err) { |
784 | printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__); | 793 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); |
785 | goto clear_hash; | 794 | goto clear_hash; |
786 | } | 795 | } |
787 | err = crypto_hash_update(desc, sg, nbytes); | 796 | err = crypto_hash_update(desc, sg, nbytes); |
788 | if (err) { | 797 | if (err) { |
789 | printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__); | 798 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); |
790 | goto clear_hash; | 799 | goto clear_hash; |
791 | } | 800 | } |
792 | err = crypto_hash_final(desc, md5_hash); | 801 | err = crypto_hash_final(desc, md5_hash); |
793 | if (err) { | 802 | if (err) { |
794 | printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__); | 803 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); |
795 | goto clear_hash; | 804 | goto clear_hash; |
796 | } | 805 | } |
797 | 806 | ||
@@ -917,7 +926,7 @@ done_opts: | |||
917 | } | 926 | } |
918 | #endif | 927 | #endif |
919 | 928 | ||
920 | static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 929 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
921 | .family = AF_INET6, | 930 | .family = AF_INET6, |
922 | .obj_size = sizeof(struct tcp6_request_sock), | 931 | .obj_size = sizeof(struct tcp6_request_sock), |
923 | .rtx_syn_ack = tcp_v6_send_synack, | 932 | .rtx_syn_ack = tcp_v6_send_synack, |
@@ -979,6 +988,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
979 | struct tcphdr *th = tcp_hdr(skb), *t1; | 988 | struct tcphdr *th = tcp_hdr(skb), *t1; |
980 | struct sk_buff *buff; | 989 | struct sk_buff *buff; |
981 | struct flowi fl; | 990 | struct flowi fl; |
991 | struct net *net = dev_net(skb->dst->dev); | ||
992 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
982 | unsigned int tot_len = sizeof(*th); | 993 | unsigned int tot_len = sizeof(*th); |
983 | #ifdef CONFIG_TCP_MD5SIG | 994 | #ifdef CONFIG_TCP_MD5SIG |
984 | struct tcp_md5sig_key *key; | 995 | struct tcp_md5sig_key *key; |
@@ -1059,11 +1070,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1059 | fl.fl_ip_sport = t1->source; | 1070 | fl.fl_ip_sport = t1->source; |
1060 | security_skb_classify_flow(skb, &fl); | 1071 | security_skb_classify_flow(skb, &fl); |
1061 | 1072 | ||
1062 | /* sk = NULL, but it is safe for now. RST socket required. */ | 1073 | /* Pass a socket to ip6_dst_lookup either it is for RST |
1063 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1074 | * Underlying function will use this to retrieve the network |
1075 | * namespace | ||
1076 | */ | ||
1077 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { | ||
1064 | 1078 | ||
1065 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1079 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1066 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1080 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1067 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1081 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1068 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); | 1082 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); |
1069 | return; | 1083 | return; |
@@ -1079,6 +1093,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1079 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1093 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1080 | struct sk_buff *buff; | 1094 | struct sk_buff *buff; |
1081 | struct flowi fl; | 1095 | struct flowi fl; |
1096 | struct net *net = dev_net(skb->dev); | ||
1097 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
1082 | unsigned int tot_len = sizeof(struct tcphdr); | 1098 | unsigned int tot_len = sizeof(struct tcphdr); |
1083 | __be32 *topt; | 1099 | __be32 *topt; |
1084 | #ifdef CONFIG_TCP_MD5SIG | 1100 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1160,9 +1176,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1160 | fl.fl_ip_sport = t1->source; | 1176 | fl.fl_ip_sport = t1->source; |
1161 | security_skb_classify_flow(skb, &fl); | 1177 | security_skb_classify_flow(skb, &fl); |
1162 | 1178 | ||
1163 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1179 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { |
1164 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1180 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1165 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1181 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1166 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1182 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1167 | return; | 1183 | return; |
1168 | } | 1184 | } |
@@ -1202,7 +1218,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1202 | if (req) | 1218 | if (req) |
1203 | return tcp_check_req(sk, skb, req, prev); | 1219 | return tcp_check_req(sk, skb, req, prev); |
1204 | 1220 | ||
1205 | nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo, | 1221 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |
1206 | &ipv6_hdr(skb)->saddr, th->source, | 1222 | &ipv6_hdr(skb)->saddr, th->source, |
1207 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); | 1223 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); |
1208 | 1224 | ||
@@ -1215,9 +1231,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1215 | return NULL; | 1231 | return NULL; |
1216 | } | 1232 | } |
1217 | 1233 | ||
1218 | #if 0 /*def CONFIG_SYN_COOKIES*/ | 1234 | #ifdef CONFIG_SYN_COOKIES |
1219 | if (!th->rst && !th->syn && th->ack) | 1235 | if (!th->rst && !th->syn && th->ack) |
1220 | sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt)); | 1236 | sk = cookie_v6_check(sk, skb); |
1221 | #endif | 1237 | #endif |
1222 | return sk; | 1238 | return sk; |
1223 | } | 1239 | } |
@@ -1233,6 +1249,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1233 | struct tcp_sock *tp = tcp_sk(sk); | 1249 | struct tcp_sock *tp = tcp_sk(sk); |
1234 | struct request_sock *req = NULL; | 1250 | struct request_sock *req = NULL; |
1235 | __u32 isn = TCP_SKB_CB(skb)->when; | 1251 | __u32 isn = TCP_SKB_CB(skb)->when; |
1252 | #ifdef CONFIG_SYN_COOKIES | ||
1253 | int want_cookie = 0; | ||
1254 | #else | ||
1255 | #define want_cookie 0 | ||
1256 | #endif | ||
1236 | 1257 | ||
1237 | if (skb->protocol == htons(ETH_P_IP)) | 1258 | if (skb->protocol == htons(ETH_P_IP)) |
1238 | return tcp_v4_conn_request(sk, skb); | 1259 | return tcp_v4_conn_request(sk, skb); |
@@ -1240,12 +1261,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1240 | if (!ipv6_unicast_destination(skb)) | 1261 | if (!ipv6_unicast_destination(skb)) |
1241 | goto drop; | 1262 | goto drop; |
1242 | 1263 | ||
1243 | /* | ||
1244 | * There are no SYN attacks on IPv6, yet... | ||
1245 | */ | ||
1246 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { | 1264 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
1247 | if (net_ratelimit()) | 1265 | if (net_ratelimit()) |
1248 | printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n"); | 1266 | syn_flood_warning(skb); |
1267 | #ifdef CONFIG_SYN_COOKIES | ||
1268 | if (sysctl_tcp_syncookies) | ||
1269 | want_cookie = 1; | ||
1270 | else | ||
1271 | #endif | ||
1249 | goto drop; | 1272 | goto drop; |
1250 | } | 1273 | } |
1251 | 1274 | ||
@@ -1266,39 +1289,51 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1266 | 1289 | ||
1267 | tcp_parse_options(skb, &tmp_opt, 0); | 1290 | tcp_parse_options(skb, &tmp_opt, 0); |
1268 | 1291 | ||
1292 | if (want_cookie) { | ||
1293 | tcp_clear_options(&tmp_opt); | ||
1294 | tmp_opt.saw_tstamp = 0; | ||
1295 | } | ||
1296 | |||
1269 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | 1297 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; |
1270 | tcp_openreq_init(req, &tmp_opt, skb); | 1298 | tcp_openreq_init(req, &tmp_opt, skb); |
1271 | 1299 | ||
1272 | treq = inet6_rsk(req); | 1300 | treq = inet6_rsk(req); |
1273 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1301 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1274 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1302 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1275 | TCP_ECN_create_request(req, tcp_hdr(skb)); | ||
1276 | treq->pktopts = NULL; | 1303 | treq->pktopts = NULL; |
1277 | if (ipv6_opt_accepted(sk, skb) || | 1304 | if (!want_cookie) |
1278 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1305 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1279 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 1306 | |
1280 | atomic_inc(&skb->users); | 1307 | if (want_cookie) { |
1281 | treq->pktopts = skb; | 1308 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); |
1282 | } | 1309 | } else if (!isn) { |
1283 | treq->iif = sk->sk_bound_dev_if; | 1310 | if (ipv6_opt_accepted(sk, skb) || |
1311 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
1312 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | ||
1313 | atomic_inc(&skb->users); | ||
1314 | treq->pktopts = skb; | ||
1315 | } | ||
1316 | treq->iif = sk->sk_bound_dev_if; | ||
1284 | 1317 | ||
1285 | /* So that link locals have meaning */ | 1318 | /* So that link locals have meaning */ |
1286 | if (!sk->sk_bound_dev_if && | 1319 | if (!sk->sk_bound_dev_if && |
1287 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1320 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1288 | treq->iif = inet6_iif(skb); | 1321 | treq->iif = inet6_iif(skb); |
1289 | 1322 | ||
1290 | if (isn == 0) | ||
1291 | isn = tcp_v6_init_sequence(skb); | 1323 | isn = tcp_v6_init_sequence(skb); |
1324 | } | ||
1292 | 1325 | ||
1293 | tcp_rsk(req)->snt_isn = isn; | 1326 | tcp_rsk(req)->snt_isn = isn; |
1294 | 1327 | ||
1295 | security_inet_conn_request(sk, skb, req); | 1328 | security_inet_conn_request(sk, skb, req); |
1296 | 1329 | ||
1297 | if (tcp_v6_send_synack(sk, req, NULL)) | 1330 | if (tcp_v6_send_synack(sk, req)) |
1298 | goto drop; | 1331 | goto drop; |
1299 | 1332 | ||
1300 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1333 | if (!want_cookie) { |
1301 | return 0; | 1334 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1335 | return 0; | ||
1336 | } | ||
1302 | 1337 | ||
1303 | drop: | 1338 | drop: |
1304 | if (req) | 1339 | if (req) |
@@ -1704,7 +1739,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1704 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1739 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); |
1705 | TCP_SKB_CB(skb)->sacked = 0; | 1740 | TCP_SKB_CB(skb)->sacked = 0; |
1706 | 1741 | ||
1707 | sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, | 1742 | sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, |
1708 | &ipv6_hdr(skb)->saddr, th->source, | 1743 | &ipv6_hdr(skb)->saddr, th->source, |
1709 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), | 1744 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), |
1710 | inet6_iif(skb)); | 1745 | inet6_iif(skb)); |
@@ -1787,7 +1822,7 @@ do_time_wait: | |||
1787 | { | 1822 | { |
1788 | struct sock *sk2; | 1823 | struct sock *sk2; |
1789 | 1824 | ||
1790 | sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo, | 1825 | sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, |
1791 | &ipv6_hdr(skb)->daddr, | 1826 | &ipv6_hdr(skb)->daddr, |
1792 | ntohs(th->dest), inet6_iif(skb)); | 1827 | ntohs(th->dest), inet6_iif(skb)); |
1793 | if (sk2 != NULL) { | 1828 | if (sk2 != NULL) { |
@@ -2094,14 +2129,14 @@ static struct tcp_seq_afinfo tcp6_seq_afinfo = { | |||
2094 | .seq_fops = &tcp6_seq_fops, | 2129 | .seq_fops = &tcp6_seq_fops, |
2095 | }; | 2130 | }; |
2096 | 2131 | ||
2097 | int __init tcp6_proc_init(void) | 2132 | int tcp6_proc_init(struct net *net) |
2098 | { | 2133 | { |
2099 | return tcp_proc_register(&tcp6_seq_afinfo); | 2134 | return tcp_proc_register(net, &tcp6_seq_afinfo); |
2100 | } | 2135 | } |
2101 | 2136 | ||
2102 | void tcp6_proc_exit(void) | 2137 | void tcp6_proc_exit(struct net *net) |
2103 | { | 2138 | { |
2104 | tcp_proc_unregister(&tcp6_seq_afinfo); | 2139 | tcp_proc_unregister(net, &tcp6_seq_afinfo); |
2105 | } | 2140 | } |
2106 | #endif | 2141 | #endif |
2107 | 2142 | ||
@@ -2137,7 +2172,7 @@ struct proto tcpv6_prot = { | |||
2137 | .obj_size = sizeof(struct tcp6_sock), | 2172 | .obj_size = sizeof(struct tcp6_sock), |
2138 | .twsk_prot = &tcp6_timewait_sock_ops, | 2173 | .twsk_prot = &tcp6_timewait_sock_ops, |
2139 | .rsk_prot = &tcp6_request_sock_ops, | 2174 | .rsk_prot = &tcp6_request_sock_ops, |
2140 | .hashinfo = &tcp_hashinfo, | 2175 | .h.hashinfo = &tcp_hashinfo, |
2141 | #ifdef CONFIG_COMPAT | 2176 | #ifdef CONFIG_COMPAT |
2142 | .compat_setsockopt = compat_tcp_setsockopt, | 2177 | .compat_setsockopt = compat_tcp_setsockopt, |
2143 | .compat_getsockopt = compat_tcp_getsockopt, | 2178 | .compat_getsockopt = compat_tcp_getsockopt, |
@@ -2164,6 +2199,31 @@ static struct inet_protosw tcpv6_protosw = { | |||
2164 | INET_PROTOSW_ICSK, | 2199 | INET_PROTOSW_ICSK, |
2165 | }; | 2200 | }; |
2166 | 2201 | ||
2202 | static int tcpv6_net_init(struct net *net) | ||
2203 | { | ||
2204 | int err; | ||
2205 | struct socket *sock; | ||
2206 | struct sock *sk; | ||
2207 | |||
2208 | err = inet_csk_ctl_sock_create(&sock, PF_INET6, SOCK_RAW, IPPROTO_TCP); | ||
2209 | if (err) | ||
2210 | return err; | ||
2211 | |||
2212 | net->ipv6.tcp_sk = sk = sock->sk; | ||
2213 | sk_change_net(sk, net); | ||
2214 | return err; | ||
2215 | } | ||
2216 | |||
2217 | static void tcpv6_net_exit(struct net *net) | ||
2218 | { | ||
2219 | sk_release_kernel(net->ipv6.tcp_sk); | ||
2220 | } | ||
2221 | |||
2222 | static struct pernet_operations tcpv6_net_ops = { | ||
2223 | .init = tcpv6_net_init, | ||
2224 | .exit = tcpv6_net_exit, | ||
2225 | }; | ||
2226 | |||
2167 | int __init tcpv6_init(void) | 2227 | int __init tcpv6_init(void) |
2168 | { | 2228 | { |
2169 | int ret; | 2229 | int ret; |
@@ -2177,8 +2237,7 @@ int __init tcpv6_init(void) | |||
2177 | if (ret) | 2237 | if (ret) |
2178 | goto out_tcpv6_protocol; | 2238 | goto out_tcpv6_protocol; |
2179 | 2239 | ||
2180 | ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, | 2240 | ret = register_pernet_subsys(&tcpv6_net_ops); |
2181 | SOCK_RAW, IPPROTO_TCP); | ||
2182 | if (ret) | 2241 | if (ret) |
2183 | goto out_tcpv6_protosw; | 2242 | goto out_tcpv6_protosw; |
2184 | out: | 2243 | out: |
@@ -2193,7 +2252,7 @@ out_tcpv6_protosw: | |||
2193 | 2252 | ||
2194 | void tcpv6_exit(void) | 2253 | void tcpv6_exit(void) |
2195 | { | 2254 | { |
2196 | sock_release(tcp6_socket); | 2255 | unregister_pernet_subsys(&tcpv6_net_ops); |
2197 | inet6_unregister_protosw(&tcpv6_protosw); | 2256 | inet6_unregister_protosw(&tcpv6_protosw); |
2198 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2257 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2199 | } | 2258 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 53739de829db..aacbc82ecf0f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -51,9 +51,9 @@ | |||
51 | #include <linux/seq_file.h> | 51 | #include <linux/seq_file.h> |
52 | #include "udp_impl.h" | 52 | #include "udp_impl.h" |
53 | 53 | ||
54 | static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) | 54 | int udp_v6_get_port(struct sock *sk, unsigned short snum) |
55 | { | 55 | { |
56 | return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); | 56 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct sock *__udp6_lib_lookup(struct net *net, | 59 | static struct sock *__udp6_lib_lookup(struct net *net, |
@@ -70,7 +70,7 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
70 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 70 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
71 | struct inet_sock *inet = inet_sk(sk); | 71 | struct inet_sock *inet = inet_sk(sk); |
72 | 72 | ||
73 | if (sk->sk_net == net && sk->sk_hash == hnum && | 73 | if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && |
74 | sk->sk_family == PF_INET6) { | 74 | sk->sk_family == PF_INET6) { |
75 | struct ipv6_pinfo *np = inet6_sk(sk); | 75 | struct ipv6_pinfo *np = inet6_sk(sk); |
76 | int score = 0; | 76 | int score = 0; |
@@ -235,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
235 | struct sock *sk; | 235 | struct sock *sk; |
236 | int err; | 236 | int err; |
237 | 237 | ||
238 | sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest, | 238 | sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest, |
239 | saddr, uh->source, inet6_iif(skb), udptable); | 239 | saddr, uh->source, inet6_iif(skb), udptable); |
240 | if (sk == NULL) | 240 | if (sk == NULL) |
241 | return; | 241 | return; |
@@ -323,6 +323,9 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
323 | sk_for_each_from(s, node) { | 323 | sk_for_each_from(s, node) { |
324 | struct inet_sock *inet = inet_sk(s); | 324 | struct inet_sock *inet = inet_sk(s); |
325 | 325 | ||
326 | if (sock_net(s) != sock_net(sk)) | ||
327 | continue; | ||
328 | |||
326 | if (s->sk_hash == num && s->sk_family == PF_INET6) { | 329 | if (s->sk_hash == num && s->sk_family == PF_INET6) { |
327 | struct ipv6_pinfo *np = inet6_sk(s); | 330 | struct ipv6_pinfo *np = inet6_sk(s); |
328 | if (inet->dport) { | 331 | if (inet->dport) { |
@@ -480,7 +483,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
480 | * check socket cache ... must talk to Alan about his plans | 483 | * check socket cache ... must talk to Alan about his plans |
481 | * for sock caches... i'll skip this for now. | 484 | * for sock caches... i'll skip this for now. |
482 | */ | 485 | */ |
483 | sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source, | 486 | sk = __udp6_lib_lookup(dev_net(skb->dev), saddr, uh->source, |
484 | daddr, uh->dest, inet6_iif(skb), udptable); | 487 | daddr, uh->dest, inet6_iif(skb), udptable); |
485 | 488 | ||
486 | if (sk == NULL) { | 489 | if (sk == NULL) { |
@@ -789,9 +792,7 @@ do_udp_sendmsg: | |||
789 | else | 792 | else |
790 | hlimit = np->hop_limit; | 793 | hlimit = np->hop_limit; |
791 | if (hlimit < 0) | 794 | if (hlimit < 0) |
792 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 795 | hlimit = ip6_dst_hoplimit(dst); |
793 | if (hlimit < 0) | ||
794 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
795 | } | 796 | } |
796 | 797 | ||
797 | if (tclass < 0) { | 798 | if (tclass < 0) { |
@@ -986,13 +987,13 @@ static struct udp_seq_afinfo udp6_seq_afinfo = { | |||
986 | .seq_fops = &udp6_seq_fops, | 987 | .seq_fops = &udp6_seq_fops, |
987 | }; | 988 | }; |
988 | 989 | ||
989 | int __init udp6_proc_init(void) | 990 | int udp6_proc_init(struct net *net) |
990 | { | 991 | { |
991 | return udp_proc_register(&udp6_seq_afinfo); | 992 | return udp_proc_register(net, &udp6_seq_afinfo); |
992 | } | 993 | } |
993 | 994 | ||
994 | void udp6_proc_exit(void) { | 995 | void udp6_proc_exit(struct net *net) { |
995 | udp_proc_unregister(&udp6_seq_afinfo); | 996 | udp_proc_unregister(net, &udp6_seq_afinfo); |
996 | } | 997 | } |
997 | #endif /* CONFIG_PROC_FS */ | 998 | #endif /* CONFIG_PROC_FS */ |
998 | 999 | ||
@@ -1021,6 +1022,7 @@ struct proto udpv6_prot = { | |||
1021 | .sysctl_wmem = &sysctl_udp_wmem_min, | 1022 | .sysctl_wmem = &sysctl_udp_wmem_min, |
1022 | .sysctl_rmem = &sysctl_udp_rmem_min, | 1023 | .sysctl_rmem = &sysctl_udp_rmem_min, |
1023 | .obj_size = sizeof(struct udp6_sock), | 1024 | .obj_size = sizeof(struct udp6_sock), |
1025 | .h.udp_hash = udp_hash, | ||
1024 | #ifdef CONFIG_COMPAT | 1026 | #ifdef CONFIG_COMPAT |
1025 | .compat_setsockopt = compat_udpv6_setsockopt, | 1027 | .compat_setsockopt = compat_udpv6_setsockopt, |
1026 | .compat_getsockopt = compat_udpv6_getsockopt, | 1028 | .compat_getsockopt = compat_udpv6_getsockopt, |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 21be3a83e7bc..321b81a4d418 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h | |||
@@ -11,6 +11,8 @@ extern int __udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int ); | |||
11 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, | 11 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, |
12 | int , int , int , __be32 , struct hlist_head []); | 12 | int , int , int , __be32 , struct hlist_head []); |
13 | 13 | ||
14 | extern int udp_v6_get_port(struct sock *sk, unsigned short snum); | ||
15 | |||
14 | extern int udpv6_getsockopt(struct sock *sk, int level, int optname, | 16 | extern int udpv6_getsockopt(struct sock *sk, int level, int optname, |
15 | char __user *optval, int __user *optlen); | 17 | char __user *optval, int __user *optlen); |
16 | extern int udpv6_setsockopt(struct sock *sk, int level, int optname, | 18 | extern int udpv6_setsockopt(struct sock *sk, int level, int optname, |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 87d4202522ee..706c5c375a01 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -35,11 +35,6 @@ static struct inet6_protocol udplitev6_protocol = { | |||
35 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 35 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static int udplite_v6_get_port(struct sock *sk, unsigned short snum) | ||
39 | { | ||
40 | return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); | ||
41 | } | ||
42 | |||
43 | DEFINE_PROTO_INUSE(udplitev6) | 38 | DEFINE_PROTO_INUSE(udplitev6) |
44 | 39 | ||
45 | struct proto udplitev6_prot = { | 40 | struct proto udplitev6_prot = { |
@@ -58,8 +53,9 @@ struct proto udplitev6_prot = { | |||
58 | .backlog_rcv = udpv6_queue_rcv_skb, | 53 | .backlog_rcv = udpv6_queue_rcv_skb, |
59 | .hash = udp_lib_hash, | 54 | .hash = udp_lib_hash, |
60 | .unhash = udp_lib_unhash, | 55 | .unhash = udp_lib_unhash, |
61 | .get_port = udplite_v6_get_port, | 56 | .get_port = udp_v6_get_port, |
62 | .obj_size = sizeof(struct udp6_sock), | 57 | .obj_size = sizeof(struct udp6_sock), |
58 | .h.udp_hash = udplite_hash, | ||
63 | #ifdef CONFIG_COMPAT | 59 | #ifdef CONFIG_COMPAT |
64 | .compat_setsockopt = compat_udpv6_setsockopt, | 60 | .compat_setsockopt = compat_udpv6_setsockopt, |
65 | .compat_getsockopt = compat_udpv6_getsockopt, | 61 | .compat_getsockopt = compat_udpv6_getsockopt, |
@@ -113,13 +109,28 @@ static struct udp_seq_afinfo udplite6_seq_afinfo = { | |||
113 | .seq_fops = &udplite6_seq_fops, | 109 | .seq_fops = &udplite6_seq_fops, |
114 | }; | 110 | }; |
115 | 111 | ||
112 | static int udplite6_proc_init_net(struct net *net) | ||
113 | { | ||
114 | return udp_proc_register(net, &udplite6_seq_afinfo); | ||
115 | } | ||
116 | |||
117 | static void udplite6_proc_exit_net(struct net *net) | ||
118 | { | ||
119 | udp_proc_unregister(net, &udplite6_seq_afinfo); | ||
120 | } | ||
121 | |||
122 | static struct pernet_operations udplite6_net_ops = { | ||
123 | .init = udplite6_proc_init_net, | ||
124 | .exit = udplite6_proc_exit_net, | ||
125 | }; | ||
126 | |||
116 | int __init udplite6_proc_init(void) | 127 | int __init udplite6_proc_init(void) |
117 | { | 128 | { |
118 | return udp_proc_register(&udplite6_seq_afinfo); | 129 | return register_pernet_subsys(&udplite6_net_ops); |
119 | } | 130 | } |
120 | 131 | ||
121 | void udplite6_proc_exit(void) | 132 | void udplite6_proc_exit(void) |
122 | { | 133 | { |
123 | udp_proc_unregister(&udplite6_seq_afinfo); | 134 | unregister_pernet_subsys(&udplite6_net_ops); |
124 | } | 135 | } |
125 | #endif | 136 | #endif |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index a4714d76ae6b..a71c7ddcb41e 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -59,9 +59,6 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
59 | xfrm_address_t *saddr, u8 proto) | 59 | xfrm_address_t *saddr, u8 proto) |
60 | { | 60 | { |
61 | struct xfrm_state *x = NULL; | 61 | struct xfrm_state *x = NULL; |
62 | int wildcard = 0; | ||
63 | xfrm_address_t *xany; | ||
64 | int nh = 0; | ||
65 | int i = 0; | 62 | int i = 0; |
66 | 63 | ||
67 | /* Allocate new secpath or COW existing one. */ | 64 | /* Allocate new secpath or COW existing one. */ |
@@ -83,10 +80,9 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
83 | goto drop; | 80 | goto drop; |
84 | } | 81 | } |
85 | 82 | ||
86 | xany = (xfrm_address_t *)&in6addr_any; | ||
87 | |||
88 | for (i = 0; i < 3; i++) { | 83 | for (i = 0; i < 3; i++) { |
89 | xfrm_address_t *dst, *src; | 84 | xfrm_address_t *dst, *src; |
85 | |||
90 | switch (i) { | 86 | switch (i) { |
91 | case 0: | 87 | case 0: |
92 | dst = daddr; | 88 | dst = daddr; |
@@ -94,16 +90,13 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
94 | break; | 90 | break; |
95 | case 1: | 91 | case 1: |
96 | /* lookup state with wild-card source address */ | 92 | /* lookup state with wild-card source address */ |
97 | wildcard = 1; | ||
98 | dst = daddr; | 93 | dst = daddr; |
99 | src = xany; | 94 | src = (xfrm_address_t *)&in6addr_any; |
100 | break; | 95 | break; |
101 | case 2: | ||
102 | default: | 96 | default: |
103 | /* lookup state with wild-card addresses */ | 97 | /* lookup state with wild-card addresses */ |
104 | wildcard = 1; /* XXX */ | 98 | dst = (xfrm_address_t *)&in6addr_any; |
105 | dst = xany; | 99 | src = (xfrm_address_t *)&in6addr_any; |
106 | src = xany; | ||
107 | break; | 100 | break; |
108 | } | 101 | } |
109 | 102 | ||
@@ -113,39 +106,19 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
113 | 106 | ||
114 | spin_lock(&x->lock); | 107 | spin_lock(&x->lock); |
115 | 108 | ||
116 | if (wildcard) { | 109 | if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) && |
117 | if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) { | 110 | likely(x->km.state == XFRM_STATE_VALID) && |
118 | spin_unlock(&x->lock); | 111 | !xfrm_state_check_expire(x)) { |
119 | xfrm_state_put(x); | ||
120 | x = NULL; | ||
121 | continue; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { | ||
126 | spin_unlock(&x->lock); | 112 | spin_unlock(&x->lock); |
127 | xfrm_state_put(x); | 113 | if (x->type->input(x, skb) > 0) { |
128 | x = NULL; | 114 | /* found a valid state */ |
129 | continue; | 115 | break; |
130 | } | 116 | } |
131 | if (xfrm_state_check_expire(x)) { | 117 | } else |
132 | spin_unlock(&x->lock); | 118 | spin_unlock(&x->lock); |
133 | xfrm_state_put(x); | ||
134 | x = NULL; | ||
135 | continue; | ||
136 | } | ||
137 | |||
138 | spin_unlock(&x->lock); | ||
139 | |||
140 | nh = x->type->input(x, skb); | ||
141 | if (nh <= 0) { | ||
142 | xfrm_state_put(x); | ||
143 | x = NULL; | ||
144 | continue; | ||
145 | } | ||
146 | 119 | ||
147 | /* Found a state */ | 120 | xfrm_state_put(x); |
148 | break; | 121 | x = NULL; |
149 | } | 122 | } |
150 | 123 | ||
151 | if (!x) { | 124 | if (!x) { |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 7d20199ee1f3..8f1e0543b3c4 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -38,7 +38,7 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr, | |||
38 | if (saddr) | 38 | if (saddr) |
39 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); | 39 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); |
40 | 40 | ||
41 | dst = ip6_route_output(NULL, &fl); | 41 | dst = ip6_route_output(&init_net, NULL, &fl); |
42 | 42 | ||
43 | err = dst->error; | 43 | err = dst->error; |
44 | if (dst->error) { | 44 | if (dst->error) { |
@@ -57,8 +57,9 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) | |||
57 | if (IS_ERR(dst)) | 57 | if (IS_ERR(dst)) |
58 | return -EHOSTUNREACH; | 58 | return -EHOSTUNREACH; |
59 | 59 | ||
60 | ipv6_get_saddr(dst, (struct in6_addr *)&daddr->a6, | 60 | ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev, |
61 | (struct in6_addr *)&saddr->a6); | 61 | (struct in6_addr *)&daddr->a6, 0, |
62 | (struct in6_addr *)&saddr->a6); | ||
62 | dst_release(dst); | 63 | dst_release(dst); |
63 | return 0; | 64 | return 0; |
64 | } | 65 | } |
@@ -246,7 +247,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
246 | xdst = (struct xfrm_dst *)dst; | 247 | xdst = (struct xfrm_dst *)dst; |
247 | if (xdst->u.rt6.rt6i_idev->dev == dev) { | 248 | if (xdst->u.rt6.rt6i_idev->dev == dev) { |
248 | struct inet6_dev *loopback_idev = | 249 | struct inet6_dev *loopback_idev = |
249 | in6_dev_get(dev->nd_net->loopback_dev); | 250 | in6_dev_get(dev_net(dev)->loopback_dev); |
250 | BUG_ON(!loopback_idev); | 251 | BUG_ON(!loopback_idev); |
251 | 252 | ||
252 | do { | 253 | do { |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index ff1e1db8e236..89884a4f23aa 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -49,125 +49,102 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
49 | x->props.family = AF_INET6; | 49 | x->props.family = AF_INET6; |
50 | } | 50 | } |
51 | 51 | ||
52 | /* distribution counting sort function for xfrm_state and xfrm_tmpl */ | ||
52 | static int | 53 | static int |
53 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | 54 | __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass) |
54 | { | 55 | { |
55 | int i; | 56 | int i; |
56 | int j = 0; | 57 | int class[XFRM_MAX_DEPTH]; |
58 | int count[maxclass]; | ||
57 | 59 | ||
58 | /* Rule 1: select IPsec transport except AH */ | 60 | memset(count, 0, sizeof(count)); |
59 | for (i = 0; i < n; i++) { | ||
60 | if (src[i]->props.mode == XFRM_MODE_TRANSPORT && | ||
61 | src[i]->id.proto != IPPROTO_AH) { | ||
62 | dst[j++] = src[i]; | ||
63 | src[i] = NULL; | ||
64 | } | ||
65 | } | ||
66 | if (j == n) | ||
67 | goto end; | ||
68 | 61 | ||
69 | /* Rule 2: select MIPv6 RO or inbound trigger */ | ||
70 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
71 | for (i = 0; i < n; i++) { | 62 | for (i = 0; i < n; i++) { |
72 | if (src[i] && | 63 | int c; |
73 | (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || | 64 | class[i] = c = cmp(src[i]); |
74 | src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) { | 65 | count[c]++; |
75 | dst[j++] = src[i]; | ||
76 | src[i] = NULL; | ||
77 | } | ||
78 | } | 66 | } |
79 | if (j == n) | ||
80 | goto end; | ||
81 | #endif | ||
82 | 67 | ||
83 | /* Rule 3: select IPsec transport AH */ | 68 | for (i = 2; i < maxclass; i++) |
84 | for (i = 0; i < n; i++) { | 69 | count[i] += count[i - 1]; |
85 | if (src[i] && | ||
86 | src[i]->props.mode == XFRM_MODE_TRANSPORT && | ||
87 | src[i]->id.proto == IPPROTO_AH) { | ||
88 | dst[j++] = src[i]; | ||
89 | src[i] = NULL; | ||
90 | } | ||
91 | } | ||
92 | if (j == n) | ||
93 | goto end; | ||
94 | 70 | ||
95 | /* Rule 4: select IPsec tunnel */ | ||
96 | for (i = 0; i < n; i++) { | 71 | for (i = 0; i < n; i++) { |
97 | if (src[i] && | 72 | dst[count[class[i] - 1]++] = src[i]; |
98 | (src[i]->props.mode == XFRM_MODE_TUNNEL || | 73 | src[i] = 0; |
99 | src[i]->props.mode == XFRM_MODE_BEET)) { | ||
100 | dst[j++] = src[i]; | ||
101 | src[i] = NULL; | ||
102 | } | ||
103 | } | 74 | } |
104 | if (likely(j == n)) | ||
105 | goto end; | ||
106 | 75 | ||
107 | /* Final rule */ | ||
108 | for (i = 0; i < n; i++) { | ||
109 | if (src[i]) { | ||
110 | dst[j++] = src[i]; | ||
111 | src[i] = NULL; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | end: | ||
116 | return 0; | 76 | return 0; |
117 | } | 77 | } |
118 | 78 | ||
119 | static int | 79 | /* |
120 | __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | 80 | * Rule for xfrm_state: |
81 | * | ||
82 | * rule 1: select IPsec transport except AH | ||
83 | * rule 2: select MIPv6 RO or inbound trigger | ||
84 | * rule 3: select IPsec transport AH | ||
85 | * rule 4: select IPsec tunnel | ||
86 | * rule 5: others | ||
87 | */ | ||
88 | static int __xfrm6_state_sort_cmp(void *p) | ||
121 | { | 89 | { |
122 | int i; | 90 | struct xfrm_state *v = p; |
123 | int j = 0; | 91 | |
124 | 92 | switch (v->props.mode) { | |
125 | /* Rule 1: select IPsec transport */ | 93 | case XFRM_MODE_TRANSPORT: |
126 | for (i = 0; i < n; i++) { | 94 | if (v->id.proto != IPPROTO_AH) |
127 | if (src[i]->mode == XFRM_MODE_TRANSPORT) { | 95 | return 1; |
128 | dst[j++] = src[i]; | 96 | else |
129 | src[i] = NULL; | 97 | return 3; |
130 | } | ||
131 | } | ||
132 | if (j == n) | ||
133 | goto end; | ||
134 | |||
135 | /* Rule 2: select MIPv6 RO or inbound trigger */ | ||
136 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 98 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
137 | for (i = 0; i < n; i++) { | 99 | case XFRM_MODE_ROUTEOPTIMIZATION: |
138 | if (src[i] && | 100 | case XFRM_MODE_IN_TRIGGER: |
139 | (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || | 101 | return 2; |
140 | src[i]->mode == XFRM_MODE_IN_TRIGGER)) { | ||
141 | dst[j++] = src[i]; | ||
142 | src[i] = NULL; | ||
143 | } | ||
144 | } | ||
145 | if (j == n) | ||
146 | goto end; | ||
147 | #endif | 102 | #endif |
148 | 103 | case XFRM_MODE_TUNNEL: | |
149 | /* Rule 3: select IPsec tunnel */ | 104 | case XFRM_MODE_BEET: |
150 | for (i = 0; i < n; i++) { | 105 | return 4; |
151 | if (src[i] && | ||
152 | (src[i]->mode == XFRM_MODE_TUNNEL || | ||
153 | src[i]->mode == XFRM_MODE_BEET)) { | ||
154 | dst[j++] = src[i]; | ||
155 | src[i] = NULL; | ||
156 | } | ||
157 | } | 106 | } |
158 | if (likely(j == n)) | 107 | return 5; |
159 | goto end; | 108 | } |
160 | 109 | ||
161 | /* Final rule */ | 110 | static int |
162 | for (i = 0; i < n; i++) { | 111 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) |
163 | if (src[i]) { | 112 | { |
164 | dst[j++] = src[i]; | 113 | return __xfrm6_sort((void **)dst, (void **)src, n, |
165 | src[i] = NULL; | 114 | __xfrm6_state_sort_cmp, 6); |
166 | } | 115 | } |
116 | |||
117 | /* | ||
118 | * Rule for xfrm_tmpl: | ||
119 | * | ||
120 | * rule 1: select IPsec transport | ||
121 | * rule 2: select MIPv6 RO or inbound trigger | ||
122 | * rule 3: select IPsec tunnel | ||
123 | * rule 4: others | ||
124 | */ | ||
125 | static int __xfrm6_tmpl_sort_cmp(void *p) | ||
126 | { | ||
127 | struct xfrm_tmpl *v = p; | ||
128 | switch (v->mode) { | ||
129 | case XFRM_MODE_TRANSPORT: | ||
130 | return 1; | ||
131 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
132 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
133 | case XFRM_MODE_IN_TRIGGER: | ||
134 | return 2; | ||
135 | #endif | ||
136 | case XFRM_MODE_TUNNEL: | ||
137 | case XFRM_MODE_BEET: | ||
138 | return 3; | ||
167 | } | 139 | } |
140 | return 4; | ||
141 | } | ||
168 | 142 | ||
169 | end: | 143 | static int |
170 | return 0; | 144 | __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) |
145 | { | ||
146 | return __xfrm6_sort((void **)dst, (void **)src, n, | ||
147 | __xfrm6_tmpl_sort_cmp, 5); | ||
171 | } | 148 | } |
172 | 149 | ||
173 | int xfrm6_extract_header(struct sk_buff *skb) | 150 | int xfrm6_extract_header(struct sk_buff *skb) |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 639fe8a6ff1e..c2b278138604 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -140,12 +140,26 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) | |||
140 | 140 | ||
141 | EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); | 141 | EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); |
142 | 142 | ||
143 | static int __xfrm6_tunnel_spi_check(u32 spi) | ||
144 | { | ||
145 | struct xfrm6_tunnel_spi *x6spi; | ||
146 | int index = xfrm6_tunnel_spi_hash_byspi(spi); | ||
147 | struct hlist_node *pos; | ||
148 | |||
149 | hlist_for_each_entry(x6spi, pos, | ||
150 | &xfrm6_tunnel_spi_byspi[index], | ||
151 | list_byspi) { | ||
152 | if (x6spi->spi == spi) | ||
153 | return -1; | ||
154 | } | ||
155 | return index; | ||
156 | } | ||
157 | |||
143 | static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) | 158 | static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) |
144 | { | 159 | { |
145 | u32 spi; | 160 | u32 spi; |
146 | struct xfrm6_tunnel_spi *x6spi; | 161 | struct xfrm6_tunnel_spi *x6spi; |
147 | struct hlist_node *pos; | 162 | int index; |
148 | unsigned index; | ||
149 | 163 | ||
150 | if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || | 164 | if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || |
151 | xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) | 165 | xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) |
@@ -154,32 +168,19 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) | |||
154 | xfrm6_tunnel_spi++; | 168 | xfrm6_tunnel_spi++; |
155 | 169 | ||
156 | for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { | 170 | for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { |
157 | index = xfrm6_tunnel_spi_hash_byspi(spi); | 171 | index = __xfrm6_tunnel_spi_check(spi); |
158 | hlist_for_each_entry(x6spi, pos, | 172 | if (index >= 0) |
159 | &xfrm6_tunnel_spi_byspi[index], | 173 | goto alloc_spi; |
160 | list_byspi) { | ||
161 | if (x6spi->spi == spi) | ||
162 | goto try_next_1; | ||
163 | } | ||
164 | xfrm6_tunnel_spi = spi; | ||
165 | goto alloc_spi; | ||
166 | try_next_1:; | ||
167 | } | 174 | } |
168 | for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { | 175 | for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { |
169 | index = xfrm6_tunnel_spi_hash_byspi(spi); | 176 | index = __xfrm6_tunnel_spi_check(spi); |
170 | hlist_for_each_entry(x6spi, pos, | 177 | if (index >= 0) |
171 | &xfrm6_tunnel_spi_byspi[index], | 178 | goto alloc_spi; |
172 | list_byspi) { | ||
173 | if (x6spi->spi == spi) | ||
174 | goto try_next_2; | ||
175 | } | ||
176 | xfrm6_tunnel_spi = spi; | ||
177 | goto alloc_spi; | ||
178 | try_next_2:; | ||
179 | } | 179 | } |
180 | spi = 0; | 180 | spi = 0; |
181 | goto out; | 181 | goto out; |
182 | alloc_spi: | 182 | alloc_spi: |
183 | xfrm6_tunnel_spi = spi; | ||
183 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); | 184 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); |
184 | if (!x6spi) | 185 | if (!x6spi) |
185 | goto out; | 186 | goto out; |