diff options
Diffstat (limited to 'net/ipv6')
31 files changed, 1655 insertions, 919 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 58219dfffef8..47263e45bacb 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -179,11 +179,12 @@ config IPV6_SIT | |||
179 | Saying M here will produce a module called sit.ko. If unsure, say Y. | 179 | Saying M here will produce a module called sit.ko. If unsure, say Y. |
180 | 180 | ||
181 | config IPV6_TUNNEL | 181 | config IPV6_TUNNEL |
182 | tristate "IPv6: IPv6-in-IPv6 tunnel" | 182 | tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)" |
183 | select INET6_TUNNEL | 183 | select INET6_TUNNEL |
184 | depends on IPV6 | 184 | depends on IPV6 |
185 | ---help--- | 185 | ---help--- |
186 | Support for IPv6-in-IPv6 tunnels described in RFC 2473. | 186 | Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in |
187 | RFC 2473. | ||
187 | 188 | ||
188 | If unsure, say N. | 189 | If unsure, say N. |
189 | 190 | ||
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..4b86d388bf63 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -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(idev->dev->nd_net, 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 = ifp->idev->dev->nd_net; | |
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) { |
@@ -905,6 +905,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
905 | { | 905 | { |
906 | struct ipv6_saddr_score hiscore; | 906 | struct ipv6_saddr_score hiscore; |
907 | struct inet6_ifaddr *ifa_result = NULL; | 907 | struct inet6_ifaddr *ifa_result = NULL; |
908 | struct net *net = daddr_dev->nd_net; | ||
908 | int daddr_type = __ipv6_addr_type(daddr); | 909 | int daddr_type = __ipv6_addr_type(daddr); |
909 | int daddr_scope = __ipv6_addr_src_scope(daddr_type); | 910 | int daddr_scope = __ipv6_addr_src_scope(daddr_type); |
910 | int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0; | 911 | int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0; |
@@ -916,7 +917,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
916 | read_lock(&dev_base_lock); | 917 | read_lock(&dev_base_lock); |
917 | rcu_read_lock(); | 918 | rcu_read_lock(); |
918 | 919 | ||
919 | for_each_netdev(&init_net, dev) { | 920 | for_each_netdev(net, dev) { |
920 | struct inet6_dev *idev; | 921 | struct inet6_dev *idev; |
921 | struct inet6_ifaddr *ifa; | 922 | struct inet6_ifaddr *ifa; |
922 | 923 | ||
@@ -1125,6 +1126,11 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
1125 | if (hiscore.rule < 7) | 1126 | if (hiscore.rule < 7) |
1126 | hiscore.rule++; | 1127 | hiscore.rule++; |
1127 | #endif | 1128 | #endif |
1129 | |||
1130 | /* Skip rule 8 for orchid -> non-orchid address pairs. */ | ||
1131 | if (ipv6_addr_orchid(&ifa->addr) && !ipv6_addr_orchid(daddr)) | ||
1132 | continue; | ||
1133 | |||
1128 | /* Rule 8: Use longest matching prefix */ | 1134 | /* Rule 8: Use longest matching prefix */ |
1129 | if (hiscore.rule < 8) { | 1135 | if (hiscore.rule < 8) { |
1130 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | 1136 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); |
@@ -1162,14 +1168,7 @@ record_it: | |||
1162 | return 0; | 1168 | return 0; |
1163 | } | 1169 | } |
1164 | 1170 | ||
1165 | 1171 | 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 | 1172 | ||
1174 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1173 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
1175 | unsigned char banned_flags) | 1174 | unsigned char banned_flags) |
@@ -1557,7 +1556,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
1557 | .fc_expires = expires, | 1556 | .fc_expires = expires, |
1558 | .fc_dst_len = plen, | 1557 | .fc_dst_len = plen, |
1559 | .fc_flags = RTF_UP | flags, | 1558 | .fc_flags = RTF_UP | flags, |
1560 | .fc_nlinfo.nl_net = &init_net, | 1559 | .fc_nlinfo.nl_net = dev->nd_net, |
1561 | }; | 1560 | }; |
1562 | 1561 | ||
1563 | ipv6_addr_copy(&cfg.fc_dst, pfx); | 1562 | ipv6_addr_copy(&cfg.fc_dst, pfx); |
@@ -1584,7 +1583,7 @@ static void addrconf_add_mroute(struct net_device *dev) | |||
1584 | .fc_ifindex = dev->ifindex, | 1583 | .fc_ifindex = dev->ifindex, |
1585 | .fc_dst_len = 8, | 1584 | .fc_dst_len = 8, |
1586 | .fc_flags = RTF_UP, | 1585 | .fc_flags = RTF_UP, |
1587 | .fc_nlinfo.nl_net = &init_net, | 1586 | .fc_nlinfo.nl_net = dev->nd_net, |
1588 | }; | 1587 | }; |
1589 | 1588 | ||
1590 | ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); | 1589 | ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); |
@@ -1601,7 +1600,7 @@ static void sit_route_add(struct net_device *dev) | |||
1601 | .fc_ifindex = dev->ifindex, | 1600 | .fc_ifindex = dev->ifindex, |
1602 | .fc_dst_len = 96, | 1601 | .fc_dst_len = 96, |
1603 | .fc_flags = RTF_UP | RTF_NONEXTHOP, | 1602 | .fc_flags = RTF_UP | RTF_NONEXTHOP, |
1604 | .fc_nlinfo.nl_net = &init_net, | 1603 | .fc_nlinfo.nl_net = dev->nd_net, |
1605 | }; | 1604 | }; |
1606 | 1605 | ||
1607 | /* prefix length - 96 bits "::d.d.d.d" */ | 1606 | /* prefix length - 96 bits "::d.d.d.d" */ |
@@ -1702,7 +1701,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1702 | 1701 | ||
1703 | if (pinfo->onlink) { | 1702 | if (pinfo->onlink) { |
1704 | struct rt6_info *rt; | 1703 | struct rt6_info *rt; |
1705 | rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1); | 1704 | rt = rt6_lookup(dev->nd_net, &pinfo->prefix, NULL, |
1705 | dev->ifindex, 1); | ||
1706 | 1706 | ||
1707 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 1707 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { |
1708 | if (rt->rt6i_flags&RTF_EXPIRES) { | 1708 | if (rt->rt6i_flags&RTF_EXPIRES) { |
@@ -1745,7 +1745,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1745 | 1745 | ||
1746 | ok: | 1746 | ok: |
1747 | 1747 | ||
1748 | ifp = ipv6_get_ifaddr(&init_net, &addr, dev, 1); | 1748 | ifp = ipv6_get_ifaddr(dev->nd_net, &addr, dev, 1); |
1749 | 1749 | ||
1750 | if (ifp == NULL && valid_lft) { | 1750 | if (ifp == NULL && valid_lft) { |
1751 | int max_addresses = in6_dev->cnf.max_addresses; | 1751 | int max_addresses = in6_dev->cnf.max_addresses; |
@@ -1868,7 +1868,7 @@ ok: | |||
1868 | * Special case for SIT interfaces where we create a new "virtual" | 1868 | * Special case for SIT interfaces where we create a new "virtual" |
1869 | * device. | 1869 | * device. |
1870 | */ | 1870 | */ |
1871 | int addrconf_set_dstaddr(void __user *arg) | 1871 | int addrconf_set_dstaddr(struct net *net, void __user *arg) |
1872 | { | 1872 | { |
1873 | struct in6_ifreq ireq; | 1873 | struct in6_ifreq ireq; |
1874 | struct net_device *dev; | 1874 | struct net_device *dev; |
@@ -1880,7 +1880,7 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1880 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) | 1880 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) |
1881 | goto err_exit; | 1881 | goto err_exit; |
1882 | 1882 | ||
1883 | dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex); | 1883 | dev = __dev_get_by_index(net, ireq.ifr6_ifindex); |
1884 | 1884 | ||
1885 | err = -ENODEV; | 1885 | err = -ENODEV; |
1886 | if (dev == NULL) | 1886 | if (dev == NULL) |
@@ -1911,7 +1911,8 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1911 | 1911 | ||
1912 | if (err == 0) { | 1912 | if (err == 0) { |
1913 | err = -ENOBUFS; | 1913 | err = -ENOBUFS; |
1914 | if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL) | 1914 | dev = __dev_get_by_name(net, p.name); |
1915 | if (!dev) | ||
1915 | goto err_exit; | 1916 | goto err_exit; |
1916 | err = dev_open(dev); | 1917 | err = dev_open(dev); |
1917 | } | 1918 | } |
@@ -1926,8 +1927,9 @@ err_exit: | |||
1926 | /* | 1927 | /* |
1927 | * Manual configuration of address on an interface | 1928 | * Manual configuration of address on an interface |
1928 | */ | 1929 | */ |
1929 | static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | 1930 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, |
1930 | __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft) | 1931 | int plen, __u8 ifa_flags, __u32 prefered_lft, |
1932 | __u32 valid_lft) | ||
1931 | { | 1933 | { |
1932 | struct inet6_ifaddr *ifp; | 1934 | struct inet6_ifaddr *ifp; |
1933 | struct inet6_dev *idev; | 1935 | struct inet6_dev *idev; |
@@ -1941,7 +1943,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1941 | if (!valid_lft || prefered_lft > valid_lft) | 1943 | if (!valid_lft || prefered_lft > valid_lft) |
1942 | return -EINVAL; | 1944 | return -EINVAL; |
1943 | 1945 | ||
1944 | if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL) | 1946 | dev = __dev_get_by_index(net, ifindex); |
1947 | if (!dev) | ||
1945 | return -ENODEV; | 1948 | return -ENODEV; |
1946 | 1949 | ||
1947 | if ((idev = addrconf_add_dev(dev)) == NULL) | 1950 | if ((idev = addrconf_add_dev(dev)) == NULL) |
@@ -1986,13 +1989,15 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1986 | return PTR_ERR(ifp); | 1989 | return PTR_ERR(ifp); |
1987 | } | 1990 | } |
1988 | 1991 | ||
1989 | static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) | 1992 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, |
1993 | int plen) | ||
1990 | { | 1994 | { |
1991 | struct inet6_ifaddr *ifp; | 1995 | struct inet6_ifaddr *ifp; |
1992 | struct inet6_dev *idev; | 1996 | struct inet6_dev *idev; |
1993 | struct net_device *dev; | 1997 | struct net_device *dev; |
1994 | 1998 | ||
1995 | if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL) | 1999 | dev = __dev_get_by_index(net, ifindex); |
2000 | if (!dev) | ||
1996 | return -ENODEV; | 2001 | return -ENODEV; |
1997 | 2002 | ||
1998 | if ((idev = __in6_dev_get(dev)) == NULL) | 2003 | if ((idev = __in6_dev_get(dev)) == NULL) |
@@ -2020,7 +2025,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) | |||
2020 | } | 2025 | } |
2021 | 2026 | ||
2022 | 2027 | ||
2023 | int addrconf_add_ifaddr(void __user *arg) | 2028 | int addrconf_add_ifaddr(struct net *net, void __user *arg) |
2024 | { | 2029 | { |
2025 | struct in6_ifreq ireq; | 2030 | struct in6_ifreq ireq; |
2026 | int err; | 2031 | int err; |
@@ -2032,13 +2037,14 @@ int addrconf_add_ifaddr(void __user *arg) | |||
2032 | return -EFAULT; | 2037 | return -EFAULT; |
2033 | 2038 | ||
2034 | rtnl_lock(); | 2039 | rtnl_lock(); |
2035 | err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, | 2040 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, |
2036 | IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 2041 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, |
2042 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | ||
2037 | rtnl_unlock(); | 2043 | rtnl_unlock(); |
2038 | return err; | 2044 | return err; |
2039 | } | 2045 | } |
2040 | 2046 | ||
2041 | int addrconf_del_ifaddr(void __user *arg) | 2047 | int addrconf_del_ifaddr(struct net *net, void __user *arg) |
2042 | { | 2048 | { |
2043 | struct in6_ifreq ireq; | 2049 | struct in6_ifreq ireq; |
2044 | int err; | 2050 | int err; |
@@ -2050,7 +2056,8 @@ int addrconf_del_ifaddr(void __user *arg) | |||
2050 | return -EFAULT; | 2056 | return -EFAULT; |
2051 | 2057 | ||
2052 | rtnl_lock(); | 2058 | rtnl_lock(); |
2053 | err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); | 2059 | err = inet6_addr_del(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, |
2060 | ireq.ifr6_prefixlen); | ||
2054 | rtnl_unlock(); | 2061 | rtnl_unlock(); |
2055 | return err; | 2062 | return err; |
2056 | } | 2063 | } |
@@ -2061,6 +2068,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2061 | struct inet6_ifaddr * ifp; | 2068 | struct inet6_ifaddr * ifp; |
2062 | struct in6_addr addr; | 2069 | struct in6_addr addr; |
2063 | struct net_device *dev; | 2070 | struct net_device *dev; |
2071 | struct net *net = idev->dev->nd_net; | ||
2064 | int scope; | 2072 | int scope; |
2065 | 2073 | ||
2066 | ASSERT_RTNL(); | 2074 | ASSERT_RTNL(); |
@@ -2087,7 +2095,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2087 | return; | 2095 | return; |
2088 | } | 2096 | } |
2089 | 2097 | ||
2090 | for_each_netdev(&init_net, dev) { | 2098 | for_each_netdev(net, dev) { |
2091 | struct in_device * in_dev = __in_dev_get_rtnl(dev); | 2099 | struct in_device * in_dev = __in_dev_get_rtnl(dev); |
2092 | if (in_dev && (dev->flags & IFF_UP)) { | 2100 | if (in_dev && (dev->flags & IFF_UP)) { |
2093 | struct in_ifaddr * ifa; | 2101 | struct in_ifaddr * ifa; |
@@ -2250,15 +2258,16 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | |||
2250 | static void ip6_tnl_add_linklocal(struct inet6_dev *idev) | 2258 | static void ip6_tnl_add_linklocal(struct inet6_dev *idev) |
2251 | { | 2259 | { |
2252 | struct net_device *link_dev; | 2260 | struct net_device *link_dev; |
2261 | struct net *net = idev->dev->nd_net; | ||
2253 | 2262 | ||
2254 | /* first try to inherit the link-local address from the link device */ | 2263 | /* first try to inherit the link-local address from the link device */ |
2255 | if (idev->dev->iflink && | 2264 | if (idev->dev->iflink && |
2256 | (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) { | 2265 | (link_dev = __dev_get_by_index(net, idev->dev->iflink))) { |
2257 | if (!ipv6_inherit_linklocal(idev, link_dev)) | 2266 | if (!ipv6_inherit_linklocal(idev, link_dev)) |
2258 | return; | 2267 | return; |
2259 | } | 2268 | } |
2260 | /* then try to inherit it from any device */ | 2269 | /* then try to inherit it from any device */ |
2261 | for_each_netdev(&init_net, link_dev) { | 2270 | for_each_netdev(net, link_dev) { |
2262 | if (!ipv6_inherit_linklocal(idev, link_dev)) | 2271 | if (!ipv6_inherit_linklocal(idev, link_dev)) |
2263 | return; | 2272 | return; |
2264 | } | 2273 | } |
@@ -2291,9 +2300,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2291 | int run_pending = 0; | 2300 | int run_pending = 0; |
2292 | int err; | 2301 | int err; |
2293 | 2302 | ||
2294 | if (dev->nd_net != &init_net) | ||
2295 | return NOTIFY_DONE; | ||
2296 | |||
2297 | switch(event) { | 2303 | switch(event) { |
2298 | case NETDEV_REGISTER: | 2304 | case NETDEV_REGISTER: |
2299 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2305 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
@@ -2433,6 +2439,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2433 | { | 2439 | { |
2434 | struct inet6_dev *idev; | 2440 | struct inet6_dev *idev; |
2435 | struct inet6_ifaddr *ifa, **bifa; | 2441 | struct inet6_ifaddr *ifa, **bifa; |
2442 | struct net *net = dev->nd_net; | ||
2436 | int i; | 2443 | int i; |
2437 | 2444 | ||
2438 | ASSERT_RTNL(); | 2445 | ASSERT_RTNL(); |
@@ -2440,7 +2447,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2440 | if (dev == init_net.loopback_dev && how == 1) | 2447 | if (dev == init_net.loopback_dev && how == 1) |
2441 | how = 0; | 2448 | how = 0; |
2442 | 2449 | ||
2443 | rt6_ifdown(dev); | 2450 | rt6_ifdown(net, dev); |
2444 | neigh_ifdown(&nd_tbl, dev); | 2451 | neigh_ifdown(&nd_tbl, dev); |
2445 | 2452 | ||
2446 | idev = __in6_dev_get(dev); | 2453 | idev = __in6_dev_get(dev); |
@@ -3050,9 +3057,6 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3050 | struct in6_addr *pfx; | 3057 | struct in6_addr *pfx; |
3051 | int err; | 3058 | int err; |
3052 | 3059 | ||
3053 | if (net != &init_net) | ||
3054 | return -EINVAL; | ||
3055 | |||
3056 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3060 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3057 | if (err < 0) | 3061 | if (err < 0) |
3058 | return err; | 3062 | return err; |
@@ -3062,7 +3066,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3062 | if (pfx == NULL) | 3066 | if (pfx == NULL) |
3063 | return -EINVAL; | 3067 | return -EINVAL; |
3064 | 3068 | ||
3065 | return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); | 3069 | return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen); |
3066 | } | 3070 | } |
3067 | 3071 | ||
3068 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | 3072 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, |
@@ -3115,9 +3119,6 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3115 | u8 ifa_flags; | 3119 | u8 ifa_flags; |
3116 | int err; | 3120 | int err; |
3117 | 3121 | ||
3118 | if (net != &init_net) | ||
3119 | return -EINVAL; | ||
3120 | |||
3121 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3122 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3122 | if (err < 0) | 3123 | if (err < 0) |
3123 | return err; | 3124 | return err; |
@@ -3138,7 +3139,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3138 | valid_lft = INFINITY_LIFE_TIME; | 3139 | valid_lft = INFINITY_LIFE_TIME; |
3139 | } | 3140 | } |
3140 | 3141 | ||
3141 | dev = __dev_get_by_index(&init_net, ifm->ifa_index); | 3142 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3142 | if (dev == NULL) | 3143 | if (dev == NULL) |
3143 | return -ENODEV; | 3144 | return -ENODEV; |
3144 | 3145 | ||
@@ -3151,8 +3152,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 | 3152 | * It would be best to check for !NLM_F_CREATE here but |
3152 | * userspace alreay relies on not having to provide this. | 3153 | * userspace alreay relies on not having to provide this. |
3153 | */ | 3154 | */ |
3154 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, | 3155 | return inet6_addr_add(net, ifm->ifa_index, pfx, |
3155 | ifa_flags, preferred_lft, valid_lft); | 3156 | ifm->ifa_prefixlen, ifa_flags, |
3157 | preferred_lft, valid_lft); | ||
3156 | } | 3158 | } |
3157 | 3159 | ||
3158 | if (nlh->nlmsg_flags & NLM_F_EXCL || | 3160 | if (nlh->nlmsg_flags & NLM_F_EXCL || |
@@ -3317,12 +3319,13 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3317 | struct inet6_ifaddr *ifa; | 3319 | struct inet6_ifaddr *ifa; |
3318 | struct ifmcaddr6 *ifmca; | 3320 | struct ifmcaddr6 *ifmca; |
3319 | struct ifacaddr6 *ifaca; | 3321 | struct ifacaddr6 *ifaca; |
3322 | struct net *net = skb->sk->sk_net; | ||
3320 | 3323 | ||
3321 | s_idx = cb->args[0]; | 3324 | s_idx = cb->args[0]; |
3322 | s_ip_idx = ip_idx = cb->args[1]; | 3325 | s_ip_idx = ip_idx = cb->args[1]; |
3323 | 3326 | ||
3324 | idx = 0; | 3327 | idx = 0; |
3325 | for_each_netdev(&init_net, dev) { | 3328 | for_each_netdev(net, dev) { |
3326 | if (idx < s_idx) | 3329 | if (idx < s_idx) |
3327 | goto cont; | 3330 | goto cont; |
3328 | if (idx > s_idx) | 3331 | if (idx > s_idx) |
@@ -3389,35 +3392,23 @@ cont: | |||
3389 | 3392 | ||
3390 | static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3393 | static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3391 | { | 3394 | { |
3392 | struct net *net = skb->sk->sk_net; | ||
3393 | enum addr_type_t type = UNICAST_ADDR; | 3395 | enum addr_type_t type = UNICAST_ADDR; |
3394 | 3396 | ||
3395 | if (net != &init_net) | ||
3396 | return 0; | ||
3397 | |||
3398 | return inet6_dump_addr(skb, cb, type); | 3397 | return inet6_dump_addr(skb, cb, type); |
3399 | } | 3398 | } |
3400 | 3399 | ||
3401 | static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3400 | static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3402 | { | 3401 | { |
3403 | struct net *net = skb->sk->sk_net; | ||
3404 | enum addr_type_t type = MULTICAST_ADDR; | 3402 | enum addr_type_t type = MULTICAST_ADDR; |
3405 | 3403 | ||
3406 | if (net != &init_net) | ||
3407 | return 0; | ||
3408 | |||
3409 | return inet6_dump_addr(skb, cb, type); | 3404 | return inet6_dump_addr(skb, cb, type); |
3410 | } | 3405 | } |
3411 | 3406 | ||
3412 | 3407 | ||
3413 | static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3408 | static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3414 | { | 3409 | { |
3415 | struct net *net = skb->sk->sk_net; | ||
3416 | enum addr_type_t type = ANYCAST_ADDR; | 3410 | enum addr_type_t type = ANYCAST_ADDR; |
3417 | 3411 | ||
3418 | if (net != &init_net) | ||
3419 | return 0; | ||
3420 | |||
3421 | return inet6_dump_addr(skb, cb, type); | 3412 | return inet6_dump_addr(skb, cb, type); |
3422 | } | 3413 | } |
3423 | 3414 | ||
@@ -3433,9 +3424,6 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3433 | struct sk_buff *skb; | 3424 | struct sk_buff *skb; |
3434 | int err; | 3425 | int err; |
3435 | 3426 | ||
3436 | if (net != &init_net) | ||
3437 | return -EINVAL; | ||
3438 | |||
3439 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3427 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3440 | if (err < 0) | 3428 | if (err < 0) |
3441 | goto errout; | 3429 | goto errout; |
@@ -3448,7 +3436,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3448 | 3436 | ||
3449 | ifm = nlmsg_data(nlh); | 3437 | ifm = nlmsg_data(nlh); |
3450 | if (ifm->ifa_index) | 3438 | if (ifm->ifa_index) |
3451 | dev = __dev_get_by_index(&init_net, ifm->ifa_index); | 3439 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3452 | 3440 | ||
3453 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3441 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { |
3454 | err = -EADDRNOTAVAIL; | 3442 | err = -EADDRNOTAVAIL; |
@@ -3468,7 +3456,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3468 | kfree_skb(skb); | 3456 | kfree_skb(skb); |
3469 | goto errout_ifa; | 3457 | goto errout_ifa; |
3470 | } | 3458 | } |
3471 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 3459 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
3472 | errout_ifa: | 3460 | errout_ifa: |
3473 | in6_ifa_put(ifa); | 3461 | in6_ifa_put(ifa); |
3474 | errout: | 3462 | errout: |
@@ -3478,6 +3466,7 @@ errout: | |||
3478 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | 3466 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) |
3479 | { | 3467 | { |
3480 | struct sk_buff *skb; | 3468 | struct sk_buff *skb; |
3469 | struct net *net = ifa->idev->dev->nd_net; | ||
3481 | int err = -ENOBUFS; | 3470 | int err = -ENOBUFS; |
3482 | 3471 | ||
3483 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); | 3472 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); |
@@ -3491,10 +3480,10 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3491 | kfree_skb(skb); | 3480 | kfree_skb(skb); |
3492 | goto errout; | 3481 | goto errout; |
3493 | } | 3482 | } |
3494 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3483 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3495 | errout: | 3484 | errout: |
3496 | if (err < 0) | 3485 | if (err < 0) |
3497 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err); | 3486 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
3498 | } | 3487 | } |
3499 | 3488 | ||
3500 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | 3489 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, |
@@ -3659,12 +3648,9 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
3659 | struct net_device *dev; | 3648 | struct net_device *dev; |
3660 | struct inet6_dev *idev; | 3649 | struct inet6_dev *idev; |
3661 | 3650 | ||
3662 | if (net != &init_net) | ||
3663 | return 0; | ||
3664 | |||
3665 | read_lock(&dev_base_lock); | 3651 | read_lock(&dev_base_lock); |
3666 | idx = 0; | 3652 | idx = 0; |
3667 | for_each_netdev(&init_net, dev) { | 3653 | for_each_netdev(net, dev) { |
3668 | if (idx < s_idx) | 3654 | if (idx < s_idx) |
3669 | goto cont; | 3655 | goto cont; |
3670 | if ((idev = in6_dev_get(dev)) == NULL) | 3656 | if ((idev = in6_dev_get(dev)) == NULL) |
@@ -3686,6 +3672,7 @@ cont: | |||
3686 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | 3672 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) |
3687 | { | 3673 | { |
3688 | struct sk_buff *skb; | 3674 | struct sk_buff *skb; |
3675 | struct net *net = idev->dev->nd_net; | ||
3689 | int err = -ENOBUFS; | 3676 | int err = -ENOBUFS; |
3690 | 3677 | ||
3691 | skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); | 3678 | skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); |
@@ -3699,10 +3686,10 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3699 | kfree_skb(skb); | 3686 | kfree_skb(skb); |
3700 | goto errout; | 3687 | goto errout; |
3701 | } | 3688 | } |
3702 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3689 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3703 | errout: | 3690 | errout: |
3704 | if (err < 0) | 3691 | if (err < 0) |
3705 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err); | 3692 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
3706 | } | 3693 | } |
3707 | 3694 | ||
3708 | static inline size_t inet6_prefix_nlmsg_size(void) | 3695 | static inline size_t inet6_prefix_nlmsg_size(void) |
@@ -3755,6 +3742,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3755 | struct prefix_info *pinfo) | 3742 | struct prefix_info *pinfo) |
3756 | { | 3743 | { |
3757 | struct sk_buff *skb; | 3744 | struct sk_buff *skb; |
3745 | struct net *net = idev->dev->nd_net; | ||
3758 | int err = -ENOBUFS; | 3746 | int err = -ENOBUFS; |
3759 | 3747 | ||
3760 | skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); | 3748 | skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); |
@@ -3768,10 +3756,10 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3768 | kfree_skb(skb); | 3756 | kfree_skb(skb); |
3769 | goto errout; | 3757 | goto errout; |
3770 | } | 3758 | } |
3771 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3759 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3772 | errout: | 3760 | errout: |
3773 | if (err < 0) | 3761 | if (err < 0) |
3774 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err); | 3762 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
3775 | } | 3763 | } |
3776 | 3764 | ||
3777 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 3765 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
@@ -4261,6 +4249,32 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
4261 | 4249 | ||
4262 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4250 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4263 | 4251 | ||
4252 | |||
4253 | static int addrconf_net_init(struct net *net) | ||
4254 | { | ||
4255 | return 0; | ||
4256 | } | ||
4257 | |||
4258 | static void addrconf_net_exit(struct net *net) | ||
4259 | { | ||
4260 | struct net_device *dev; | ||
4261 | |||
4262 | rtnl_lock(); | ||
4263 | /* clean dev list */ | ||
4264 | for_each_netdev(net, dev) { | ||
4265 | if (__in6_dev_get(dev) == NULL) | ||
4266 | continue; | ||
4267 | addrconf_ifdown(dev, 1); | ||
4268 | } | ||
4269 | addrconf_ifdown(net->loopback_dev, 2); | ||
4270 | rtnl_unlock(); | ||
4271 | } | ||
4272 | |||
4273 | static struct pernet_operations addrconf_net_ops = { | ||
4274 | .init = addrconf_net_init, | ||
4275 | .exit = addrconf_net_exit, | ||
4276 | }; | ||
4277 | |||
4264 | /* | 4278 | /* |
4265 | * Init / cleanup code | 4279 | * Init / cleanup code |
4266 | */ | 4280 | */ |
@@ -4302,14 +4316,9 @@ int __init addrconf_init(void) | |||
4302 | if (err) | 4316 | if (err) |
4303 | goto errlo; | 4317 | goto errlo; |
4304 | 4318 | ||
4305 | ip6_null_entry.u.dst.dev = init_net.loopback_dev; | 4319 | err = register_pernet_device(&addrconf_net_ops); |
4306 | ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | 4320 | if (err) |
4307 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 4321 | 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 | 4322 | ||
4314 | register_netdevice_notifier(&ipv6_dev_notf); | 4323 | register_netdevice_notifier(&ipv6_dev_notf); |
4315 | 4324 | ||
@@ -4339,31 +4348,19 @@ errlo: | |||
4339 | 4348 | ||
4340 | void addrconf_cleanup(void) | 4349 | void addrconf_cleanup(void) |
4341 | { | 4350 | { |
4342 | struct net_device *dev; | ||
4343 | struct inet6_ifaddr *ifa; | 4351 | struct inet6_ifaddr *ifa; |
4344 | int i; | 4352 | int i; |
4345 | 4353 | ||
4346 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4354 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4355 | unregister_pernet_device(&addrconf_net_ops); | ||
4347 | 4356 | ||
4348 | unregister_pernet_subsys(&addrconf_ops); | 4357 | unregister_pernet_subsys(&addrconf_ops); |
4349 | 4358 | ||
4350 | rtnl_lock(); | 4359 | rtnl_lock(); |
4351 | 4360 | ||
4352 | /* | 4361 | /* |
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. | 4362 | * Check hash table. |
4365 | */ | 4363 | */ |
4366 | |||
4367 | write_lock_bh(&addrconf_hash_lock); | 4364 | write_lock_bh(&addrconf_hash_lock); |
4368 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4365 | for (i=0; i < IN6_ADDR_HSIZE; i++) { |
4369 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4366 | for (ifa=inet6_addr_lst[i]; ifa; ) { |
@@ -4380,6 +4377,7 @@ void addrconf_cleanup(void) | |||
4380 | write_unlock_bh(&addrconf_hash_lock); | 4377 | write_unlock_bh(&addrconf_hash_lock); |
4381 | 4378 | ||
4382 | del_timer(&addr_chk_timer); | 4379 | del_timer(&addr_chk_timer); |
4383 | |||
4384 | rtnl_unlock(); | 4380 | rtnl_unlock(); |
4381 | |||
4382 | unregister_pernet_subsys(&addrconf_net_ops); | ||
4385 | } | 4383 | } |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index a3c5a72218fd..de371b5997fe 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, |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index f0aa97738746..f52bdaed8a1b 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 = sk->sk_net; | ||
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 = sk->sk_net; | ||
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,30 @@ 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 | out: | ||
866 | #endif | ||
867 | return err; | ||
868 | |||
869 | #ifdef CONFIG_PROC_FS | ||
870 | proc_tcp6_fail: | ||
871 | udp6_proc_exit(net); | ||
872 | goto out; | ||
873 | #endif | ||
735 | } | 874 | } |
736 | 875 | ||
737 | static void inet6_net_exit(struct net *net) | 876 | static void inet6_net_exit(struct net *net) |
738 | { | 877 | { |
739 | return; | 878 | #ifdef CONFIG_PROC_FS |
879 | udp6_proc_exit(net); | ||
880 | tcp6_proc_exit(net); | ||
881 | #endif | ||
740 | } | 882 | } |
741 | 883 | ||
742 | static struct pernet_operations inet6_net_ops = { | 884 | static struct pernet_operations inet6_net_ops = { |
@@ -802,19 +944,13 @@ static int __init inet6_init(void) | |||
802 | err = register_pernet_subsys(&inet6_net_ops); | 944 | err = register_pernet_subsys(&inet6_net_ops); |
803 | if (err) | 945 | if (err) |
804 | goto register_pernet_fail; | 946 | goto register_pernet_fail; |
805 | 947 | 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) | 948 | if (err) |
813 | goto icmp_fail; | 949 | goto icmp_fail; |
814 | err = ndisc_init(&inet6_family_ops); | 950 | err = ndisc_init(); |
815 | if (err) | 951 | if (err) |
816 | goto ndisc_fail; | 952 | goto ndisc_fail; |
817 | err = igmp6_init(&inet6_family_ops); | 953 | err = igmp6_init(); |
818 | if (err) | 954 | if (err) |
819 | goto igmp_fail; | 955 | goto igmp_fail; |
820 | err = ipv6_netfilter_init(); | 956 | err = ipv6_netfilter_init(); |
@@ -825,10 +961,6 @@ static int __init inet6_init(void) | |||
825 | err = -ENOMEM; | 961 | err = -ENOMEM; |
826 | if (raw6_proc_init()) | 962 | if (raw6_proc_init()) |
827 | goto proc_raw6_fail; | 963 | 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()) | 964 | if (udplite6_proc_init()) |
833 | goto proc_udplite6_fail; | 965 | goto proc_udplite6_fail; |
834 | if (ipv6_misc_proc_init()) | 966 | if (ipv6_misc_proc_init()) |
@@ -874,9 +1006,19 @@ static int __init inet6_init(void) | |||
874 | err = ipv6_packet_init(); | 1006 | err = ipv6_packet_init(); |
875 | if (err) | 1007 | if (err) |
876 | goto ipv6_packet_fail; | 1008 | goto ipv6_packet_fail; |
1009 | |||
1010 | #ifdef CONFIG_SYSCTL | ||
1011 | err = ipv6_sysctl_register(); | ||
1012 | if (err) | ||
1013 | goto sysctl_fail; | ||
1014 | #endif | ||
877 | out: | 1015 | out: |
878 | return err; | 1016 | return err; |
879 | 1017 | ||
1018 | #ifdef CONFIG_SYSCTL | ||
1019 | sysctl_fail: | ||
1020 | ipv6_packet_cleanup(); | ||
1021 | #endif | ||
880 | ipv6_packet_fail: | 1022 | ipv6_packet_fail: |
881 | tcpv6_exit(); | 1023 | tcpv6_exit(); |
882 | tcpv6_fail: | 1024 | tcpv6_fail: |
@@ -903,10 +1045,6 @@ proc_anycast6_fail: | |||
903 | proc_misc6_fail: | 1045 | proc_misc6_fail: |
904 | udplite6_proc_exit(); | 1046 | udplite6_proc_exit(); |
905 | proc_udplite6_fail: | 1047 | proc_udplite6_fail: |
906 | udp6_proc_exit(); | ||
907 | proc_udp6_fail: | ||
908 | tcp6_proc_exit(); | ||
909 | proc_tcp6_fail: | ||
910 | raw6_proc_exit(); | 1048 | raw6_proc_exit(); |
911 | proc_raw6_fail: | 1049 | proc_raw6_fail: |
912 | #endif | 1050 | #endif |
@@ -918,10 +1056,6 @@ igmp_fail: | |||
918 | ndisc_fail: | 1056 | ndisc_fail: |
919 | icmpv6_cleanup(); | 1057 | icmpv6_cleanup(); |
920 | icmp_fail: | 1058 | icmp_fail: |
921 | #ifdef CONFIG_SYSCTL | ||
922 | ipv6_sysctl_unregister(); | ||
923 | sysctl_fail: | ||
924 | #endif | ||
925 | unregister_pernet_subsys(&inet6_net_ops); | 1059 | unregister_pernet_subsys(&inet6_net_ops); |
926 | register_pernet_fail: | 1060 | register_pernet_fail: |
927 | cleanup_ipv6_mibs(); | 1061 | cleanup_ipv6_mibs(); |
@@ -949,6 +1083,9 @@ static void __exit inet6_exit(void) | |||
949 | /* Disallow any further netlink messages */ | 1083 | /* Disallow any further netlink messages */ |
950 | rtnl_unregister_all(PF_INET6); | 1084 | rtnl_unregister_all(PF_INET6); |
951 | 1085 | ||
1086 | #ifdef CONFIG_SYSCTL | ||
1087 | ipv6_sysctl_unregister(); | ||
1088 | #endif | ||
952 | udpv6_exit(); | 1089 | udpv6_exit(); |
953 | udplitev6_exit(); | 1090 | udplitev6_exit(); |
954 | tcpv6_exit(); | 1091 | tcpv6_exit(); |
@@ -967,8 +1104,6 @@ static void __exit inet6_exit(void) | |||
967 | ac6_proc_exit(); | 1104 | 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..96868b994b37 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -101,7 +101,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
101 | if (ifindex == 0) { | 101 | if (ifindex == 0) { |
102 | struct rt6_info *rt; | 102 | struct rt6_info *rt; |
103 | 103 | ||
104 | rt = rt6_lookup(addr, NULL, 0, 0); | 104 | rt = rt6_lookup(&init_net, addr, NULL, 0, 0); |
105 | if (rt) { | 105 | if (rt) { |
106 | dev = rt->rt6i_dev; | 106 | dev = rt->rt6i_dev; |
107 | dev_hold(dev); | 107 | dev_hold(dev); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 695c0ca8a417..55137408f054 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,8 @@ 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 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, |
89 | &saddr)) | 88 | &flp->fl6_dst, &saddr)) |
90 | goto again; | 89 | goto again; |
91 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 90 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
92 | r->src.plen)) | 91 | r->src.plen)) |
@@ -145,13 +144,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
145 | struct nlattr **tb) | 144 | struct nlattr **tb) |
146 | { | 145 | { |
147 | int err = -EINVAL; | 146 | int err = -EINVAL; |
147 | struct net *net = skb->sk->sk_net; | ||
148 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 148 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
149 | 149 | ||
150 | if (rule->action == FR_ACT_TO_TBL) { | 150 | if (rule->action == FR_ACT_TO_TBL) { |
151 | if (rule->table == RT6_TABLE_UNSPEC) | 151 | if (rule->table == RT6_TABLE_UNSPEC) |
152 | goto errout; | 152 | goto errout; |
153 | 153 | ||
154 | if (fib6_new_table(rule->table) == NULL) { | 154 | if (fib6_new_table(net, rule->table) == NULL) { |
155 | err = -ENOBUFS; | 155 | err = -ENOBUFS; |
156 | goto errout; | 156 | goto errout; |
157 | } | 157 | } |
@@ -234,7 +234,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
234 | + nla_total_size(16); /* src */ | 234 | + nla_total_size(16); /* src */ |
235 | } | 235 | } |
236 | 236 | ||
237 | static struct fib_rules_ops fib6_rules_ops = { | 237 | static struct fib_rules_ops fib6_rules_ops_template = { |
238 | .family = AF_INET6, | 238 | .family = AF_INET6, |
239 | .rule_size = sizeof(struct fib6_rule), | 239 | .rule_size = sizeof(struct fib6_rule), |
240 | .addr_size = sizeof(struct in6_addr), | 240 | .addr_size = sizeof(struct in6_addr), |
@@ -247,45 +247,64 @@ static struct fib_rules_ops fib6_rules_ops = { | |||
247 | .nlmsg_payload = fib6_rule_nlmsg_payload, | 247 | .nlmsg_payload = fib6_rule_nlmsg_payload, |
248 | .nlgroup = RTNLGRP_IPV6_RULE, | 248 | .nlgroup = RTNLGRP_IPV6_RULE, |
249 | .policy = fib6_rule_policy, | 249 | .policy = fib6_rule_policy, |
250 | .rules_list = LIST_HEAD_INIT(fib6_rules_ops.rules_list), | ||
251 | .owner = THIS_MODULE, | 250 | .owner = THIS_MODULE, |
252 | .fro_net = &init_net, | 251 | .fro_net = &init_net, |
253 | }; | 252 | }; |
254 | 253 | ||
255 | static int __init fib6_default_rules_init(void) | 254 | static int fib6_rules_net_init(struct net *net) |
256 | { | 255 | { |
257 | int err; | 256 | int err = -ENOMEM; |
258 | 257 | ||
259 | err = fib_default_rule_add(&fib6_rules_ops, 0, | 258 | net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template, |
260 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); | 259 | sizeof(*net->ipv6.fib6_rules_ops), |
261 | if (err < 0) | 260 | GFP_KERNEL); |
262 | return err; | 261 | if (!net->ipv6.fib6_rules_ops) |
263 | err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0); | 262 | goto out; |
264 | if (err < 0) | ||
265 | return err; | ||
266 | return 0; | ||
267 | } | ||
268 | 263 | ||
269 | int __init fib6_rules_init(void) | 264 | net->ipv6.fib6_rules_ops->fro_net = net; |
270 | { | 265 | INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list); |
271 | int ret; | ||
272 | 266 | ||
273 | ret = fib6_default_rules_init(); | 267 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0, |
274 | if (ret) | 268 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); |
275 | goto out; | 269 | if (err) |
270 | goto out_fib6_rules_ops; | ||
276 | 271 | ||
277 | ret = fib_rules_register(&fib6_rules_ops); | 272 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, |
278 | if (ret) | 273 | 0x7FFE, RT6_TABLE_MAIN, 0); |
279 | goto out_default_rules_init; | 274 | if (err) |
275 | goto out_fib6_default_rule_add; | ||
276 | |||
277 | err = fib_rules_register(net->ipv6.fib6_rules_ops); | ||
278 | if (err) | ||
279 | goto out_fib6_default_rule_add; | ||
280 | out: | 280 | out: |
281 | return ret; | 281 | return err; |
282 | 282 | ||
283 | out_default_rules_init: | 283 | out_fib6_default_rule_add: |
284 | fib_rules_cleanup_ops(&fib6_rules_ops); | 284 | fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops); |
285 | out_fib6_rules_ops: | ||
286 | kfree(net->ipv6.fib6_rules_ops); | ||
285 | goto out; | 287 | goto out; |
286 | } | 288 | } |
287 | 289 | ||
290 | static void fib6_rules_net_exit(struct net *net) | ||
291 | { | ||
292 | fib_rules_unregister(net->ipv6.fib6_rules_ops); | ||
293 | kfree(net->ipv6.fib6_rules_ops); | ||
294 | } | ||
295 | |||
296 | static struct pernet_operations fib6_rules_net_ops = { | ||
297 | .init = fib6_rules_net_init, | ||
298 | .exit = fib6_rules_net_exit, | ||
299 | }; | ||
300 | |||
301 | int __init fib6_rules_init(void) | ||
302 | { | ||
303 | return register_pernet_subsys(&fib6_rules_net_ops); | ||
304 | } | ||
305 | |||
306 | |||
288 | void fib6_rules_cleanup(void) | 307 | void fib6_rules_cleanup(void) |
289 | { | 308 | { |
290 | fib_rules_unregister(&fib6_rules_ops); | 309 | return unregister_pernet_subsys(&fib6_rules_net_ops); |
291 | } | 310 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 121d517bf91c..6b5391ab8346 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 = sk->sk_net; | ||
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 = skb->dev->nd_net; | ||
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 | ||
@@ -498,13 +502,14 @@ out_put: | |||
498 | out_dst_release: | 502 | out_dst_release: |
499 | dst_release(dst); | 503 | dst_release(dst); |
500 | out: | 504 | out: |
501 | icmpv6_xmit_unlock(); | 505 | icmpv6_xmit_unlock(sk); |
502 | } | 506 | } |
503 | 507 | ||
504 | EXPORT_SYMBOL(icmpv6_send); | 508 | EXPORT_SYMBOL(icmpv6_send); |
505 | 509 | ||
506 | static void icmpv6_echo_reply(struct sk_buff *skb) | 510 | static void icmpv6_echo_reply(struct sk_buff *skb) |
507 | { | 511 | { |
512 | struct net *net = skb->dev->nd_net; | ||
508 | struct sock *sk; | 513 | struct sock *sk; |
509 | struct inet6_dev *idev; | 514 | struct inet6_dev *idev; |
510 | struct ipv6_pinfo *np; | 515 | struct ipv6_pinfo *np; |
@@ -535,12 +540,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
535 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 540 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; |
536 | security_skb_classify_flow(skb, &fl); | 541 | security_skb_classify_flow(skb, &fl); |
537 | 542 | ||
538 | if (icmpv6_xmit_lock()) | 543 | sk = icmpv6_sk(net); |
539 | return; | ||
540 | |||
541 | sk = icmpv6_socket->sk; | ||
542 | np = inet6_sk(sk); | 544 | np = inet6_sk(sk); |
543 | 545 | ||
546 | if (icmpv6_xmit_lock(sk)) | ||
547 | return; | ||
548 | |||
544 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 549 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
545 | fl.oif = np->mcast_oif; | 550 | fl.oif = np->mcast_oif; |
546 | 551 | ||
@@ -584,7 +589,7 @@ out_put: | |||
584 | in6_dev_put(idev); | 589 | in6_dev_put(idev); |
585 | dst_release(dst); | 590 | dst_release(dst); |
586 | out: | 591 | out: |
587 | icmpv6_xmit_unlock(); | 592 | icmpv6_xmit_unlock(sk); |
588 | } | 593 | } |
589 | 594 | ||
590 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | 595 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) |
@@ -775,19 +780,41 @@ drop_no_count: | |||
775 | return 0; | 780 | return 0; |
776 | } | 781 | } |
777 | 782 | ||
783 | void icmpv6_flow_init(struct sock *sk, struct flowi *fl, | ||
784 | u8 type, | ||
785 | const struct in6_addr *saddr, | ||
786 | const struct in6_addr *daddr, | ||
787 | int oif) | ||
788 | { | ||
789 | memset(fl, 0, sizeof(*fl)); | ||
790 | ipv6_addr_copy(&fl->fl6_src, saddr); | ||
791 | ipv6_addr_copy(&fl->fl6_dst, daddr); | ||
792 | fl->proto = IPPROTO_ICMPV6; | ||
793 | fl->fl_icmp_type = type; | ||
794 | fl->fl_icmp_code = 0; | ||
795 | fl->oif = oif; | ||
796 | security_sk_classify_flow(sk, fl); | ||
797 | } | ||
798 | |||
778 | /* | 799 | /* |
779 | * Special lock-class for __icmpv6_socket: | 800 | * Special lock-class for __icmpv6_sk: |
780 | */ | 801 | */ |
781 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; | 802 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; |
782 | 803 | ||
783 | int __init icmpv6_init(struct net_proto_family *ops) | 804 | static int __net_init icmpv6_sk_init(struct net *net) |
784 | { | 805 | { |
785 | struct sock *sk; | 806 | struct sock *sk; |
786 | int err, i, j; | 807 | int err, i, j; |
787 | 808 | ||
809 | net->ipv6.icmp_sk = | ||
810 | kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); | ||
811 | if (net->ipv6.icmp_sk == NULL) | ||
812 | return -ENOMEM; | ||
813 | |||
788 | for_each_possible_cpu(i) { | 814 | for_each_possible_cpu(i) { |
815 | struct socket *sock; | ||
789 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, | 816 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, |
790 | &per_cpu(__icmpv6_socket, i)); | 817 | &sock); |
791 | if (err < 0) { | 818 | if (err < 0) { |
792 | printk(KERN_ERR | 819 | printk(KERN_ERR |
793 | "Failed to initialize the ICMP6 control socket " | 820 | "Failed to initialize the ICMP6 control socket " |
@@ -796,12 +823,14 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
796 | goto fail; | 823 | goto fail; |
797 | } | 824 | } |
798 | 825 | ||
799 | sk = per_cpu(__icmpv6_socket, i)->sk; | 826 | net->ipv6.icmp_sk[i] = sk = sock->sk; |
827 | sk_change_net(sk, net); | ||
828 | |||
800 | sk->sk_allocation = GFP_ATOMIC; | 829 | sk->sk_allocation = GFP_ATOMIC; |
801 | /* | 830 | /* |
802 | * Split off their lock-class, because sk->sk_dst_lock | 831 | * Split off their lock-class, because sk->sk_dst_lock |
803 | * gets used from softirqs, which is safe for | 832 | * gets used from softirqs, which is safe for |
804 | * __icmpv6_socket (because those never get directly used | 833 | * __icmpv6_sk (because those never get directly used |
805 | * via userspace syscalls), but unsafe for normal sockets. | 834 | * via userspace syscalls), but unsafe for normal sockets. |
806 | */ | 835 | */ |
807 | lockdep_set_class(&sk->sk_dst_lock, | 836 | lockdep_set_class(&sk->sk_dst_lock, |
@@ -815,36 +844,56 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
815 | 844 | ||
816 | sk->sk_prot->unhash(sk); | 845 | sk->sk_prot->unhash(sk); |
817 | } | 846 | } |
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; | 847 | return 0; |
827 | 848 | ||
828 | fail: | 849 | fail: |
829 | for (j = 0; j < i; j++) { | 850 | for (j = 0; j < i; j++) |
830 | if (!cpu_possible(j)) | 851 | sk_release_kernel(net->ipv6.icmp_sk[j]); |
831 | continue; | 852 | kfree(net->ipv6.icmp_sk); |
832 | sock_release(per_cpu(__icmpv6_socket, j)); | ||
833 | } | ||
834 | |||
835 | return err; | 853 | return err; |
836 | } | 854 | } |
837 | 855 | ||
838 | void icmpv6_cleanup(void) | 856 | static void __net_exit icmpv6_sk_exit(struct net *net) |
839 | { | 857 | { |
840 | int i; | 858 | int i; |
841 | 859 | ||
842 | for_each_possible_cpu(i) { | 860 | for_each_possible_cpu(i) { |
843 | sock_release(per_cpu(__icmpv6_socket, i)); | 861 | sk_release_kernel(net->ipv6.icmp_sk[i]); |
844 | } | 862 | } |
863 | kfree(net->ipv6.icmp_sk); | ||
864 | } | ||
865 | |||
866 | static struct pernet_operations icmpv6_sk_ops = { | ||
867 | .init = icmpv6_sk_init, | ||
868 | .exit = icmpv6_sk_exit, | ||
869 | }; | ||
870 | |||
871 | int __init icmpv6_init(void) | ||
872 | { | ||
873 | int err; | ||
874 | |||
875 | err = register_pernet_subsys(&icmpv6_sk_ops); | ||
876 | if (err < 0) | ||
877 | return err; | ||
878 | |||
879 | err = -EAGAIN; | ||
880 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) | ||
881 | goto fail; | ||
882 | return 0; | ||
883 | |||
884 | fail: | ||
885 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
886 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
887 | return err; | ||
888 | } | ||
889 | |||
890 | void icmpv6_cleanup(void) | ||
891 | { | ||
892 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
845 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | 893 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); |
846 | } | 894 | } |
847 | 895 | ||
896 | |||
848 | static const struct icmp6_err { | 897 | static const struct icmp6_err { |
849 | int err; | 898 | int err; |
850 | int fatal; | 899 | int fatal; |
@@ -925,6 +974,10 @@ struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) | |||
925 | table = kmemdup(ipv6_icmp_table_template, | 974 | table = kmemdup(ipv6_icmp_table_template, |
926 | sizeof(ipv6_icmp_table_template), | 975 | sizeof(ipv6_icmp_table_template), |
927 | GFP_KERNEL); | 976 | GFP_KERNEL); |
977 | |||
978 | if (table) | ||
979 | table[0].data = &net->ipv6.sysctl.icmpv6_time; | ||
980 | |||
928 | return table; | 981 | return table; |
929 | } | 982 | } |
930 | #endif | 983 | #endif |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 99fd25f7f005..c0c8d2d17682 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 | ||
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index bab72b6f1444..b0814b0082e7 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 |
@@ -368,11 +353,9 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
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_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..98762fde2b65 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -404,6 +404,7 @@ int ip6_forward(struct sk_buff *skb) | |||
404 | struct dst_entry *dst = skb->dst; | 404 | struct dst_entry *dst = skb->dst; |
405 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 405 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
406 | struct inet6_skb_parm *opt = IP6CB(skb); | 406 | struct inet6_skb_parm *opt = IP6CB(skb); |
407 | struct net *net = dst->dev->nd_net; | ||
407 | 408 | ||
408 | if (ipv6_devconf.forwarding == 0) | 409 | if (ipv6_devconf.forwarding == 0) |
409 | goto error; | 410 | goto error; |
@@ -450,7 +451,7 @@ int ip6_forward(struct sk_buff *skb) | |||
450 | 451 | ||
451 | /* XXX: idev->cnf.proxy_ndp? */ | 452 | /* XXX: idev->cnf.proxy_ndp? */ |
452 | if (ipv6_devconf.proxy_ndp && | 453 | if (ipv6_devconf.proxy_ndp && |
453 | pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) { | 454 | pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) { |
454 | int proxied = ip6_forward_proxy_check(skb); | 455 | int proxied = ip6_forward_proxy_check(skb); |
455 | if (proxied > 0) | 456 | if (proxied > 0) |
456 | return ip6_input(skb); | 457 | return ip6_input(skb); |
@@ -596,7 +597,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
596 | 597 | ||
597 | return offset; | 598 | return offset; |
598 | } | 599 | } |
599 | EXPORT_SYMBOL_GPL(ip6_find_1stfragopt); | ||
600 | 600 | ||
601 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 601 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
602 | { | 602 | { |
@@ -912,15 +912,17 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
912 | struct dst_entry **dst, struct flowi *fl) | 912 | struct dst_entry **dst, struct flowi *fl) |
913 | { | 913 | { |
914 | int err; | 914 | int err; |
915 | struct net *net = sk->sk_net; | ||
915 | 916 | ||
916 | if (*dst == NULL) | 917 | if (*dst == NULL) |
917 | *dst = ip6_route_output(sk, fl); | 918 | *dst = ip6_route_output(net, sk, fl); |
918 | 919 | ||
919 | if ((err = (*dst)->error)) | 920 | if ((err = (*dst)->error)) |
920 | goto out_err_release; | 921 | goto out_err_release; |
921 | 922 | ||
922 | if (ipv6_addr_any(&fl->fl6_src)) { | 923 | if (ipv6_addr_any(&fl->fl6_src)) { |
923 | err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); | 924 | err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev, |
925 | &fl->fl6_dst, &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 | } |
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..c11c76cab371 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 = sk->sk_net; | ||
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 | } |
@@ -1128,13 +1017,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1128 | EXPORT_SYMBOL(compat_ipv6_getsockopt); | 1017 | EXPORT_SYMBOL(compat_ipv6_getsockopt); |
1129 | #endif | 1018 | #endif |
1130 | 1019 | ||
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..957ac7e9e929 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 = sk->sk_net; | ||
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 = sk->sk_net; | ||
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 = sk->sk_net; | ||
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 = sk->sk_net; | ||
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 = sk->sk_net; | ||
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 = sk->sk_net; | ||
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->nd_net; |
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 = skb->dev->nd_net; | ||
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->nd_net; |
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 = state->p.net; | ||
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 = state->p.net; | ||
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 0d33a7d32125..24e76ed98884 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->nd_net; |
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,7 +539,7 @@ 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->nd_net, 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) |
@@ -616,7 +599,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
616 | * suppress the inclusion of the sllao. | 599 | * suppress the inclusion of the sllao. |
617 | */ | 600 | */ |
618 | if (send_sllao) { | 601 | if (send_sllao) { |
619 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr, | 602 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev->nd_net, saddr, |
620 | dev, 1); | 603 | dev, 1); |
621 | if (ifp) { | 604 | if (ifp) { |
622 | if (ifp->flags & IFA_F_OPTIMISTIC) { | 605 | if (ifp->flags & IFA_F_OPTIMISTIC) { |
@@ -654,7 +637,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
654 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; | 637 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; |
655 | int probes = atomic_read(&neigh->probes); | 638 | int probes = atomic_read(&neigh->probes); |
656 | 639 | ||
657 | if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1)) | 640 | if (skb && ipv6_chk_addr(dev->nd_net, &ipv6_hdr(skb)->saddr, dev, 1)) |
658 | saddr = &ipv6_hdr(skb)->saddr; | 641 | saddr = &ipv6_hdr(skb)->saddr; |
659 | 642 | ||
660 | if ((probes -= neigh->parms->ucast_probes) < 0) { | 643 | if ((probes -= neigh->parms->ucast_probes) < 0) { |
@@ -662,7 +645,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
662 | ND_PRINTK1(KERN_DEBUG | 645 | ND_PRINTK1(KERN_DEBUG |
663 | "%s(): trying to ucast probe in NUD_INVALID: " | 646 | "%s(): trying to ucast probe in NUD_INVALID: " |
664 | NIP6_FMT "\n", | 647 | NIP6_FMT "\n", |
665 | __FUNCTION__, | 648 | __func__, |
666 | NIP6(*target)); | 649 | NIP6(*target)); |
667 | } | 650 | } |
668 | ndisc_send_ns(dev, neigh, target, target, saddr); | 651 | ndisc_send_ns(dev, neigh, target, target, saddr); |
@@ -742,7 +725,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
742 | 725 | ||
743 | inc = ipv6_addr_is_multicast(daddr); | 726 | inc = ipv6_addr_is_multicast(daddr); |
744 | 727 | ||
745 | if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) { | 728 | ifp = ipv6_get_ifaddr(dev->nd_net, &msg->target, dev, 1); |
729 | if (ifp) { | ||
746 | 730 | ||
747 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { | 731 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { |
748 | if (dad) { | 732 | if (dad) { |
@@ -790,7 +774,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
790 | if (ipv6_chk_acast_addr(dev, &msg->target) || | 774 | if (ipv6_chk_acast_addr(dev, &msg->target) || |
791 | (idev->cnf.forwarding && | 775 | (idev->cnf.forwarding && |
792 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && | 776 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && |
793 | (pneigh = pneigh_lookup(&nd_tbl, &init_net, | 777 | (pneigh = pneigh_lookup(&nd_tbl, dev->nd_net, |
794 | &msg->target, dev, 0)) != NULL)) { | 778 | &msg->target, dev, 0)) != NULL)) { |
795 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && | 779 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && |
796 | skb->pkt_type != PACKET_HOST && | 780 | skb->pkt_type != PACKET_HOST && |
@@ -900,7 +884,8 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
900 | return; | 884 | return; |
901 | } | 885 | } |
902 | } | 886 | } |
903 | if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) { | 887 | ifp = ipv6_get_ifaddr(dev->nd_net, &msg->target, dev, 1); |
888 | if (ifp) { | ||
904 | if (ifp->flags & IFA_F_TENTATIVE) { | 889 | if (ifp->flags & IFA_F_TENTATIVE) { |
905 | addrconf_dad_failure(ifp); | 890 | addrconf_dad_failure(ifp); |
906 | return; | 891 | return; |
@@ -931,7 +916,7 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
931 | */ | 916 | */ |
932 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && | 917 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && |
933 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && | 918 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && |
934 | pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) { | 919 | pneigh_lookup(&nd_tbl, dev->nd_net, &msg->target, dev, 0)) { |
935 | /* XXX: idev->cnf.prixy_ndp */ | 920 | /* XXX: idev->cnf.prixy_ndp */ |
936 | goto out; | 921 | goto out; |
937 | } | 922 | } |
@@ -1021,6 +1006,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1021 | struct sk_buff *skb; | 1006 | struct sk_buff *skb; |
1022 | struct nlmsghdr *nlh; | 1007 | struct nlmsghdr *nlh; |
1023 | struct nduseroptmsg *ndmsg; | 1008 | struct nduseroptmsg *ndmsg; |
1009 | struct net *net = ra->dev->nd_net; | ||
1024 | int err; | 1010 | int err; |
1025 | int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) | 1011 | int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) |
1026 | + (opt->nd_opt_len << 3)); | 1012 | + (opt->nd_opt_len << 3)); |
@@ -1050,7 +1036,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1050 | &ipv6_hdr(ra)->saddr); | 1036 | &ipv6_hdr(ra)->saddr); |
1051 | nlmsg_end(skb, nlh); | 1037 | nlmsg_end(skb, nlh); |
1052 | 1038 | ||
1053 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL, | 1039 | err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, |
1054 | GFP_ATOMIC); | 1040 | GFP_ATOMIC); |
1055 | if (err < 0) | 1041 | if (err < 0) |
1056 | goto errout; | 1042 | goto errout; |
@@ -1061,7 +1047,7 @@ nla_put_failure: | |||
1061 | nlmsg_free(skb); | 1047 | nlmsg_free(skb); |
1062 | err = -EMSGSIZE; | 1048 | err = -EMSGSIZE; |
1063 | errout: | 1049 | errout: |
1064 | rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err); | 1050 | rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err); |
1065 | } | 1051 | } |
1066 | 1052 | ||
1067 | static void ndisc_router_discovery(struct sk_buff *skb) | 1053 | static void ndisc_router_discovery(struct sk_buff *skb) |
@@ -1164,7 +1150,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1164 | if (rt == NULL) { | 1150 | if (rt == NULL) { |
1165 | ND_PRINTK0(KERN_ERR | 1151 | ND_PRINTK0(KERN_ERR |
1166 | "ICMPv6 RA: %s() failed to add default route.\n", | 1152 | "ICMPv6 RA: %s() failed to add default route.\n", |
1167 | __FUNCTION__); | 1153 | __func__); |
1168 | in6_dev_put(in6_dev); | 1154 | in6_dev_put(in6_dev); |
1169 | return; | 1155 | return; |
1170 | } | 1156 | } |
@@ -1173,7 +1159,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1173 | if (neigh == NULL) { | 1159 | if (neigh == NULL) { |
1174 | ND_PRINTK0(KERN_ERR | 1160 | ND_PRINTK0(KERN_ERR |
1175 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1161 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
1176 | __FUNCTION__); | 1162 | __func__); |
1177 | dst_release(&rt->u.dst); | 1163 | dst_release(&rt->u.dst); |
1178 | in6_dev_put(in6_dev); | 1164 | in6_dev_put(in6_dev); |
1179 | return; | 1165 | return; |
@@ -1406,13 +1392,14 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1406 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | 1392 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, |
1407 | struct in6_addr *target) | 1393 | struct in6_addr *target) |
1408 | { | 1394 | { |
1409 | struct sock *sk = ndisc_socket->sk; | 1395 | struct net_device *dev = skb->dev; |
1396 | struct net *net = dev->nd_net; | ||
1397 | struct sock *sk = net->ipv6.ndisc_sk; | ||
1410 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); | 1398 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); |
1411 | struct sk_buff *buff; | 1399 | struct sk_buff *buff; |
1412 | struct icmp6hdr *icmph; | 1400 | struct icmp6hdr *icmph; |
1413 | struct in6_addr saddr_buf; | 1401 | struct in6_addr saddr_buf; |
1414 | struct in6_addr *addrp; | 1402 | struct in6_addr *addrp; |
1415 | struct net_device *dev; | ||
1416 | struct rt6_info *rt; | 1403 | struct rt6_info *rt; |
1417 | struct dst_entry *dst; | 1404 | struct dst_entry *dst; |
1418 | struct inet6_dev *idev; | 1405 | struct inet6_dev *idev; |
@@ -1423,8 +1410,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1423 | int hlen; | 1410 | int hlen; |
1424 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; | 1411 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; |
1425 | 1412 | ||
1426 | dev = skb->dev; | ||
1427 | |||
1428 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { | 1413 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { |
1429 | ND_PRINTK2(KERN_WARNING | 1414 | ND_PRINTK2(KERN_WARNING |
1430 | "ICMPv6 Redirect: no link-local address on %s\n", | 1415 | "ICMPv6 Redirect: no link-local address on %s\n", |
@@ -1439,10 +1424,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1439 | return; | 1424 | return; |
1440 | } | 1425 | } |
1441 | 1426 | ||
1442 | ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1427 | icmpv6_flow_init(sk, &fl, NDISC_REDIRECT, |
1443 | dev->ifindex); | 1428 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); |
1444 | 1429 | ||
1445 | dst = ip6_route_output(NULL, &fl); | 1430 | dst = ip6_route_output(net, NULL, &fl); |
1446 | if (dst == NULL) | 1431 | if (dst == NULL) |
1447 | return; | 1432 | return; |
1448 | 1433 | ||
@@ -1486,7 +1471,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1486 | if (buff == NULL) { | 1471 | if (buff == NULL) { |
1487 | ND_PRINTK0(KERN_ERR | 1472 | ND_PRINTK0(KERN_ERR |
1488 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", | 1473 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", |
1489 | __FUNCTION__); | 1474 | __func__); |
1490 | dst_release(dst); | 1475 | dst_release(dst); |
1491 | return; | 1476 | return; |
1492 | } | 1477 | } |
@@ -1613,18 +1598,16 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1613 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1598 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1614 | { | 1599 | { |
1615 | struct net_device *dev = ptr; | 1600 | struct net_device *dev = ptr; |
1616 | 1601 | struct net *net = dev->nd_net; | |
1617 | if (dev->nd_net != &init_net) | ||
1618 | return NOTIFY_DONE; | ||
1619 | 1602 | ||
1620 | switch (event) { | 1603 | switch (event) { |
1621 | case NETDEV_CHANGEADDR: | 1604 | case NETDEV_CHANGEADDR: |
1622 | neigh_changeaddr(&nd_tbl, dev); | 1605 | neigh_changeaddr(&nd_tbl, dev); |
1623 | fib6_run_gc(~0UL); | 1606 | fib6_run_gc(~0UL, net); |
1624 | break; | 1607 | break; |
1625 | case NETDEV_DOWN: | 1608 | case NETDEV_DOWN: |
1626 | neigh_ifdown(&nd_tbl, dev); | 1609 | neigh_ifdown(&nd_tbl, dev); |
1627 | fib6_run_gc(~0UL); | 1610 | fib6_run_gc(~0UL, net); |
1628 | break; | 1611 | break; |
1629 | default: | 1612 | default: |
1630 | break; | 1613 | break; |
@@ -1733,22 +1716,24 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, | |||
1733 | 1716 | ||
1734 | #endif | 1717 | #endif |
1735 | 1718 | ||
1736 | int __init ndisc_init(struct net_proto_family *ops) | 1719 | static int ndisc_net_init(struct net *net) |
1737 | { | 1720 | { |
1721 | struct socket *sock; | ||
1738 | struct ipv6_pinfo *np; | 1722 | struct ipv6_pinfo *np; |
1739 | struct sock *sk; | 1723 | struct sock *sk; |
1740 | int err; | 1724 | int err; |
1741 | 1725 | ||
1742 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket); | 1726 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &sock); |
1743 | if (err < 0) { | 1727 | if (err < 0) { |
1744 | ND_PRINTK0(KERN_ERR | 1728 | ND_PRINTK0(KERN_ERR |
1745 | "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", | 1729 | "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", |
1746 | err); | 1730 | err); |
1747 | ndisc_socket = NULL; /* For safety. */ | ||
1748 | return err; | 1731 | return err; |
1749 | } | 1732 | } |
1750 | 1733 | ||
1751 | sk = ndisc_socket->sk; | 1734 | net->ipv6.ndisc_sk = sk = sock->sk; |
1735 | sk_change_net(sk, net); | ||
1736 | |||
1752 | np = inet6_sk(sk); | 1737 | np = inet6_sk(sk); |
1753 | sk->sk_allocation = GFP_ATOMIC; | 1738 | sk->sk_allocation = GFP_ATOMIC; |
1754 | np->hop_limit = 255; | 1739 | np->hop_limit = 255; |
@@ -1756,21 +1741,52 @@ int __init ndisc_init(struct net_proto_family *ops) | |||
1756 | np->mc_loop = 0; | 1741 | np->mc_loop = 0; |
1757 | sk->sk_prot->unhash(sk); | 1742 | sk->sk_prot->unhash(sk); |
1758 | 1743 | ||
1744 | return 0; | ||
1745 | } | ||
1746 | |||
1747 | static void ndisc_net_exit(struct net *net) | ||
1748 | { | ||
1749 | sk_release_kernel(net->ipv6.ndisc_sk); | ||
1750 | } | ||
1751 | |||
1752 | static struct pernet_operations ndisc_net_ops = { | ||
1753 | .init = ndisc_net_init, | ||
1754 | .exit = ndisc_net_exit, | ||
1755 | }; | ||
1756 | |||
1757 | int __init ndisc_init(void) | ||
1758 | { | ||
1759 | int err; | ||
1760 | |||
1761 | err = register_pernet_subsys(&ndisc_net_ops); | ||
1762 | if (err) | ||
1763 | return err; | ||
1759 | /* | 1764 | /* |
1760 | * Initialize the neighbour table | 1765 | * Initialize the neighbour table |
1761 | */ | 1766 | */ |
1762 | |||
1763 | neigh_table_init(&nd_tbl); | 1767 | neigh_table_init(&nd_tbl); |
1764 | 1768 | ||
1765 | #ifdef CONFIG_SYSCTL | 1769 | #ifdef CONFIG_SYSCTL |
1766 | neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, | 1770 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, |
1767 | "ipv6", | 1771 | NET_IPV6_NEIGH, "ipv6", |
1768 | &ndisc_ifinfo_sysctl_change, | 1772 | &ndisc_ifinfo_sysctl_change, |
1769 | &ndisc_ifinfo_sysctl_strategy); | 1773 | &ndisc_ifinfo_sysctl_strategy); |
1774 | if (err) | ||
1775 | goto out_unregister_pernet; | ||
1770 | #endif | 1776 | #endif |
1777 | err = register_netdevice_notifier(&ndisc_netdev_notifier); | ||
1778 | if (err) | ||
1779 | goto out_unregister_sysctl; | ||
1780 | out: | ||
1781 | return err; | ||
1771 | 1782 | ||
1772 | register_netdevice_notifier(&ndisc_netdev_notifier); | 1783 | out_unregister_sysctl: |
1773 | return 0; | 1784 | #ifdef CONFIG_SYSCTL |
1785 | neigh_sysctl_unregister(&nd_tbl.parms); | ||
1786 | out_unregister_pernet: | ||
1787 | #endif | ||
1788 | unregister_pernet_subsys(&ndisc_net_ops); | ||
1789 | goto out; | ||
1774 | } | 1790 | } |
1775 | 1791 | ||
1776 | void ndisc_cleanup(void) | 1792 | void ndisc_cleanup(void) |
@@ -1780,6 +1796,5 @@ void ndisc_cleanup(void) | |||
1780 | neigh_sysctl_unregister(&nd_tbl.parms); | 1796 | neigh_sysctl_unregister(&nd_tbl.parms); |
1781 | #endif | 1797 | #endif |
1782 | neigh_table_clear(&nd_tbl); | 1798 | neigh_table_clear(&nd_tbl); |
1783 | sock_release(ndisc_socket); | 1799 | unregister_pernet_subsys(&ndisc_net_ops); |
1784 | ndisc_socket = NULL; /* For safety. */ | ||
1785 | } | 1800 | } |
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_tables.c b/net/ipv6/netfilter/ip6_tables.c index bf9bb6e55bb5..af1ec7ba757c 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) |
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..8a5be290c710 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 (idev->dev->nd_net != &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..a9e4235157a2 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) |
@@ -1201,9 +1190,10 @@ struct proto rawv6_prot = { | |||
1201 | .recvmsg = rawv6_recvmsg, | 1190 | .recvmsg = rawv6_recvmsg, |
1202 | .bind = rawv6_bind, | 1191 | .bind = rawv6_bind, |
1203 | .backlog_rcv = rawv6_rcv_skb, | 1192 | .backlog_rcv = rawv6_rcv_skb, |
1204 | .hash = raw_v6_hash, | 1193 | .hash = raw_hash_sk, |
1205 | .unhash = raw_v6_unhash, | 1194 | .unhash = raw_unhash_sk, |
1206 | .obj_size = sizeof(struct raw6_sock), | 1195 | .obj_size = sizeof(struct raw6_sock), |
1196 | .h.raw_hash = &raw_v6_hashinfo, | ||
1207 | #ifdef CONFIG_COMPAT | 1197 | #ifdef CONFIG_COMPAT |
1208 | .compat_setsockopt = compat_rawv6_setsockopt, | 1198 | .compat_setsockopt = compat_rawv6_setsockopt, |
1209 | .compat_getsockopt = compat_rawv6_getsockopt, | 1199 | .compat_getsockopt = compat_rawv6_getsockopt, |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e8b241cb60bc..a4b5aee0f68a 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) |
@@ -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 = rt0->rt6i_dev->nd_net; |
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->nd_net; | ||
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 = rt->rt6i_dev->nd_net, |
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 = skb->dev->nd_net; | ||
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 | ||
@@ -777,7 +783,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | |||
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; |
779 | 785 | ||
780 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); | 786 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); |
781 | } | 787 | } |
782 | 788 | ||
783 | EXPORT_SYMBOL(ip6_route_output); | 789 | EXPORT_SYMBOL(ip6_route_output); |
@@ -886,12 +892,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
886 | 892 | ||
887 | static int ipv6_get_mtu(struct net_device *dev); | 893 | static int ipv6_get_mtu(struct net_device *dev); |
888 | 894 | ||
889 | static inline unsigned int ipv6_advmss(unsigned int mtu) | 895 | static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu) |
890 | { | 896 | { |
891 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); | 897 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); |
892 | 898 | ||
893 | if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss) | 899 | if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) |
894 | mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss; | 900 | mtu = net->ipv6.sysctl.ip6_rt_min_advmss; |
895 | 901 | ||
896 | /* | 902 | /* |
897 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and | 903 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and |
@@ -904,21 +910,21 @@ static inline unsigned int ipv6_advmss(unsigned int mtu) | |||
904 | return mtu; | 910 | return mtu; |
905 | } | 911 | } |
906 | 912 | ||
907 | static struct dst_entry *ndisc_dst_gc_list; | 913 | static struct dst_entry *icmp6_dst_gc_list; |
908 | static DEFINE_SPINLOCK(ndisc_lock); | 914 | static DEFINE_SPINLOCK(icmp6_dst_lock); |
909 | 915 | ||
910 | struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | 916 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
911 | struct neighbour *neigh, | 917 | struct neighbour *neigh, |
912 | struct in6_addr *addr, | 918 | struct in6_addr *addr) |
913 | int (*output)(struct sk_buff *)) | ||
914 | { | 919 | { |
915 | struct rt6_info *rt; | 920 | struct rt6_info *rt; |
916 | struct inet6_dev *idev = in6_dev_get(dev); | 921 | struct inet6_dev *idev = in6_dev_get(dev); |
922 | struct net *net = dev->nd_net; | ||
917 | 923 | ||
918 | if (unlikely(idev == NULL)) | 924 | if (unlikely(idev == NULL)) |
919 | return NULL; | 925 | return NULL; |
920 | 926 | ||
921 | rt = ip6_dst_alloc(); | 927 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
922 | if (unlikely(rt == NULL)) { | 928 | if (unlikely(rt == NULL)) { |
923 | in6_dev_put(idev); | 929 | in6_dev_put(idev); |
924 | goto out; | 930 | goto out; |
@@ -936,8 +942,8 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
936 | atomic_set(&rt->u.dst.__refcnt, 1); | 942 | atomic_set(&rt->u.dst.__refcnt, 1); |
937 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; | 943 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; |
938 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 944 | 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)); | 945 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
940 | rt->u.dst.output = output; | 946 | rt->u.dst.output = ip6_output; |
941 | 947 | ||
942 | #if 0 /* there's no chance to use these for ndisc */ | 948 | #if 0 /* there's no chance to use these for ndisc */ |
943 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | 949 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST |
@@ -947,18 +953,18 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
947 | rt->rt6i_dst.plen = 128; | 953 | rt->rt6i_dst.plen = 128; |
948 | #endif | 954 | #endif |
949 | 955 | ||
950 | spin_lock_bh(&ndisc_lock); | 956 | spin_lock_bh(&icmp6_dst_lock); |
951 | rt->u.dst.next = ndisc_dst_gc_list; | 957 | rt->u.dst.next = icmp6_dst_gc_list; |
952 | ndisc_dst_gc_list = &rt->u.dst; | 958 | icmp6_dst_gc_list = &rt->u.dst; |
953 | spin_unlock_bh(&ndisc_lock); | 959 | spin_unlock_bh(&icmp6_dst_lock); |
954 | 960 | ||
955 | fib6_force_start_gc(); | 961 | fib6_force_start_gc(net); |
956 | 962 | ||
957 | out: | 963 | out: |
958 | return &rt->u.dst; | 964 | return &rt->u.dst; |
959 | } | 965 | } |
960 | 966 | ||
961 | int ndisc_dst_gc(int *more) | 967 | int icmp6_dst_gc(int *more) |
962 | { | 968 | { |
963 | struct dst_entry *dst, *next, **pprev; | 969 | struct dst_entry *dst, *next, **pprev; |
964 | int freed; | 970 | int freed; |
@@ -966,8 +972,8 @@ int ndisc_dst_gc(int *more) | |||
966 | next = NULL; | 972 | next = NULL; |
967 | freed = 0; | 973 | freed = 0; |
968 | 974 | ||
969 | spin_lock_bh(&ndisc_lock); | 975 | spin_lock_bh(&icmp6_dst_lock); |
970 | pprev = &ndisc_dst_gc_list; | 976 | pprev = &icmp6_dst_gc_list; |
971 | 977 | ||
972 | while ((dst = *pprev) != NULL) { | 978 | while ((dst = *pprev) != NULL) { |
973 | if (!atomic_read(&dst->__refcnt)) { | 979 | if (!atomic_read(&dst->__refcnt)) { |
@@ -980,30 +986,33 @@ int ndisc_dst_gc(int *more) | |||
980 | } | 986 | } |
981 | } | 987 | } |
982 | 988 | ||
983 | spin_unlock_bh(&ndisc_lock); | 989 | spin_unlock_bh(&icmp6_dst_lock); |
984 | 990 | ||
985 | return freed; | 991 | return freed; |
986 | } | 992 | } |
987 | 993 | ||
988 | static int ip6_dst_gc(struct dst_ops *ops) | 994 | static int ip6_dst_gc(struct dst_ops *ops) |
989 | { | 995 | { |
990 | static unsigned expire = 30*HZ; | ||
991 | static unsigned long last_gc; | ||
992 | unsigned long now = jiffies; | 996 | unsigned long now = jiffies; |
993 | 997 | struct net *net = ops->dst_net; | |
994 | if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) && | 998 | 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) | 999 | int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; |
1000 | int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
1001 | int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
1002 | unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; | ||
1003 | |||
1004 | if (time_after(rt_last_gc + rt_min_interval, now) && | ||
1005 | atomic_read(&ops->entries) <= rt_max_size) | ||
996 | goto out; | 1006 | goto out; |
997 | 1007 | ||
998 | expire++; | 1008 | net->ipv6.ip6_rt_gc_expire++; |
999 | fib6_run_gc(expire); | 1009 | fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net); |
1000 | last_gc = now; | 1010 | net->ipv6.ip6_rt_last_gc = now; |
1001 | if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh) | 1011 | if (atomic_read(&ops->entries) < ops->gc_thresh) |
1002 | expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1; | 1012 | net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; |
1003 | |||
1004 | out: | 1013 | out: |
1005 | expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity; | 1014 | 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); | 1015 | return (atomic_read(&ops->entries) > rt_max_size); |
1007 | } | 1016 | } |
1008 | 1017 | ||
1009 | /* Clean host part of a prefix. Not necessary in radix tree, | 1018 | /* Clean host part of a prefix. Not necessary in radix tree, |
@@ -1045,6 +1054,7 @@ int ipv6_get_hoplimit(struct net_device *dev) | |||
1045 | int ip6_route_add(struct fib6_config *cfg) | 1054 | int ip6_route_add(struct fib6_config *cfg) |
1046 | { | 1055 | { |
1047 | int err; | 1056 | int err; |
1057 | struct net *net = cfg->fc_nlinfo.nl_net; | ||
1048 | struct rt6_info *rt = NULL; | 1058 | struct rt6_info *rt = NULL; |
1049 | struct net_device *dev = NULL; | 1059 | struct net_device *dev = NULL; |
1050 | struct inet6_dev *idev = NULL; | 1060 | struct inet6_dev *idev = NULL; |
@@ -1059,7 +1069,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1059 | #endif | 1069 | #endif |
1060 | if (cfg->fc_ifindex) { | 1070 | if (cfg->fc_ifindex) { |
1061 | err = -ENODEV; | 1071 | err = -ENODEV; |
1062 | dev = dev_get_by_index(&init_net, cfg->fc_ifindex); | 1072 | dev = dev_get_by_index(net, cfg->fc_ifindex); |
1063 | if (!dev) | 1073 | if (!dev) |
1064 | goto out; | 1074 | goto out; |
1065 | idev = in6_dev_get(dev); | 1075 | idev = in6_dev_get(dev); |
@@ -1070,13 +1080,13 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1070 | if (cfg->fc_metric == 0) | 1080 | if (cfg->fc_metric == 0) |
1071 | cfg->fc_metric = IP6_RT_PRIO_USER; | 1081 | cfg->fc_metric = IP6_RT_PRIO_USER; |
1072 | 1082 | ||
1073 | table = fib6_new_table(cfg->fc_table); | 1083 | table = fib6_new_table(net, cfg->fc_table); |
1074 | if (table == NULL) { | 1084 | if (table == NULL) { |
1075 | err = -ENOBUFS; | 1085 | err = -ENOBUFS; |
1076 | goto out; | 1086 | goto out; |
1077 | } | 1087 | } |
1078 | 1088 | ||
1079 | rt = ip6_dst_alloc(); | 1089 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
1080 | 1090 | ||
1081 | if (rt == NULL) { | 1091 | if (rt == NULL) { |
1082 | err = -ENOMEM; | 1092 | err = -ENOMEM; |
@@ -1117,12 +1127,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1117 | if ((cfg->fc_flags & RTF_REJECT) || | 1127 | if ((cfg->fc_flags & RTF_REJECT) || |
1118 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { | 1128 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { |
1119 | /* hold loopback dev/idev if we haven't done so. */ | 1129 | /* hold loopback dev/idev if we haven't done so. */ |
1120 | if (dev != init_net.loopback_dev) { | 1130 | if (dev != net->loopback_dev) { |
1121 | if (dev) { | 1131 | if (dev) { |
1122 | dev_put(dev); | 1132 | dev_put(dev); |
1123 | in6_dev_put(idev); | 1133 | in6_dev_put(idev); |
1124 | } | 1134 | } |
1125 | dev = init_net.loopback_dev; | 1135 | dev = net->loopback_dev; |
1126 | dev_hold(dev); | 1136 | dev_hold(dev); |
1127 | idev = in6_dev_get(dev); | 1137 | idev = in6_dev_get(dev); |
1128 | if (!idev) { | 1138 | if (!idev) { |
@@ -1159,7 +1169,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1159 | if (!(gwa_type&IPV6_ADDR_UNICAST)) | 1169 | if (!(gwa_type&IPV6_ADDR_UNICAST)) |
1160 | goto out; | 1170 | goto out; |
1161 | 1171 | ||
1162 | grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1); | 1172 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); |
1163 | 1173 | ||
1164 | err = -EHOSTUNREACH; | 1174 | err = -EHOSTUNREACH; |
1165 | if (grt == NULL) | 1175 | if (grt == NULL) |
@@ -1226,10 +1236,13 @@ install_route: | |||
1226 | if (!rt->u.dst.metrics[RTAX_MTU-1]) | 1236 | if (!rt->u.dst.metrics[RTAX_MTU-1]) |
1227 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1237 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); |
1228 | if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) | 1238 | if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) |
1229 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); | 1239 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
1230 | rt->u.dst.dev = dev; | 1240 | rt->u.dst.dev = dev; |
1231 | rt->rt6i_idev = idev; | 1241 | rt->rt6i_idev = idev; |
1232 | rt->rt6i_table = table; | 1242 | rt->rt6i_table = table; |
1243 | |||
1244 | cfg->fc_nlinfo.nl_net = dev->nd_net; | ||
1245 | |||
1233 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); | 1246 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); |
1234 | 1247 | ||
1235 | out: | 1248 | out: |
@@ -1246,8 +1259,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1246 | { | 1259 | { |
1247 | int err; | 1260 | int err; |
1248 | struct fib6_table *table; | 1261 | struct fib6_table *table; |
1262 | struct net *net = rt->rt6i_dev->nd_net; | ||
1249 | 1263 | ||
1250 | if (rt == &ip6_null_entry) | 1264 | if (rt == net->ipv6.ip6_null_entry) |
1251 | return -ENOENT; | 1265 | return -ENOENT; |
1252 | 1266 | ||
1253 | table = rt->rt6i_table; | 1267 | table = rt->rt6i_table; |
@@ -1264,7 +1278,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1264 | int ip6_del_rt(struct rt6_info *rt) | 1278 | int ip6_del_rt(struct rt6_info *rt) |
1265 | { | 1279 | { |
1266 | struct nl_info info = { | 1280 | struct nl_info info = { |
1267 | .nl_net = &init_net, | 1281 | .nl_net = rt->rt6i_dev->nd_net, |
1268 | }; | 1282 | }; |
1269 | return __ip6_del_rt(rt, &info); | 1283 | return __ip6_del_rt(rt, &info); |
1270 | } | 1284 | } |
@@ -1276,7 +1290,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1276 | struct rt6_info *rt; | 1290 | struct rt6_info *rt; |
1277 | int err = -ESRCH; | 1291 | int err = -ESRCH; |
1278 | 1292 | ||
1279 | table = fib6_get_table(cfg->fc_table); | 1293 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); |
1280 | if (table == NULL) | 1294 | if (table == NULL) |
1281 | return err; | 1295 | return err; |
1282 | 1296 | ||
@@ -1316,7 +1330,8 @@ struct ip6rd_flowi { | |||
1316 | struct in6_addr gateway; | 1330 | struct in6_addr gateway; |
1317 | }; | 1331 | }; |
1318 | 1332 | ||
1319 | static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, | 1333 | static struct rt6_info *__ip6_route_redirect(struct net *net, |
1334 | struct fib6_table *table, | ||
1320 | struct flowi *fl, | 1335 | struct flowi *fl, |
1321 | int flags) | 1336 | int flags) |
1322 | { | 1337 | { |
@@ -1359,8 +1374,8 @@ restart: | |||
1359 | } | 1374 | } |
1360 | 1375 | ||
1361 | if (!rt) | 1376 | if (!rt) |
1362 | rt = &ip6_null_entry; | 1377 | rt = net->ipv6.ip6_null_entry; |
1363 | BACKTRACK(&fl->fl6_src); | 1378 | BACKTRACK(net, &fl->fl6_src); |
1364 | out: | 1379 | out: |
1365 | dst_hold(&rt->u.dst); | 1380 | dst_hold(&rt->u.dst); |
1366 | 1381 | ||
@@ -1375,6 +1390,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1375 | struct net_device *dev) | 1390 | struct net_device *dev) |
1376 | { | 1391 | { |
1377 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 1392 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
1393 | struct net *net = dev->nd_net; | ||
1378 | struct ip6rd_flowi rdfl = { | 1394 | struct ip6rd_flowi rdfl = { |
1379 | .fl = { | 1395 | .fl = { |
1380 | .oif = dev->ifindex, | 1396 | .oif = dev->ifindex, |
@@ -1391,7 +1407,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1391 | if (rt6_need_strict(dest)) | 1407 | if (rt6_need_strict(dest)) |
1392 | flags |= RT6_LOOKUP_F_IFACE; | 1408 | flags |= RT6_LOOKUP_F_IFACE; |
1393 | 1409 | ||
1394 | return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); | 1410 | return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl, |
1411 | flags, __ip6_route_redirect); | ||
1395 | } | 1412 | } |
1396 | 1413 | ||
1397 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | 1414 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, |
@@ -1400,10 +1417,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1400 | { | 1417 | { |
1401 | struct rt6_info *rt, *nrt = NULL; | 1418 | struct rt6_info *rt, *nrt = NULL; |
1402 | struct netevent_redirect netevent; | 1419 | struct netevent_redirect netevent; |
1420 | struct net *net = neigh->dev->nd_net; | ||
1403 | 1421 | ||
1404 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); | 1422 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); |
1405 | 1423 | ||
1406 | if (rt == &ip6_null_entry) { | 1424 | if (rt == net->ipv6.ip6_null_entry) { |
1407 | if (net_ratelimit()) | 1425 | if (net_ratelimit()) |
1408 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " | 1426 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " |
1409 | "for redirect target\n"); | 1427 | "for redirect target\n"); |
@@ -1448,7 +1466,8 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1448 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1466 | nrt->rt6i_nexthop = neigh_clone(neigh); |
1449 | /* Reset pmtu, it may be better */ | 1467 | /* Reset pmtu, it may be better */ |
1450 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1468 | 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)); | 1469 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(neigh->dev->nd_net, |
1470 | dst_mtu(&nrt->u.dst)); | ||
1452 | 1471 | ||
1453 | if (ip6_ins_rt(nrt)) | 1472 | if (ip6_ins_rt(nrt)) |
1454 | goto out; | 1473 | goto out; |
@@ -1476,9 +1495,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1476 | struct net_device *dev, u32 pmtu) | 1495 | struct net_device *dev, u32 pmtu) |
1477 | { | 1496 | { |
1478 | struct rt6_info *rt, *nrt; | 1497 | struct rt6_info *rt, *nrt; |
1498 | struct net *net = dev->nd_net; | ||
1479 | int allfrag = 0; | 1499 | int allfrag = 0; |
1480 | 1500 | ||
1481 | rt = rt6_lookup(daddr, saddr, dev->ifindex, 0); | 1501 | rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0); |
1482 | if (rt == NULL) | 1502 | if (rt == NULL) |
1483 | return; | 1503 | return; |
1484 | 1504 | ||
@@ -1511,7 +1531,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1511 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1531 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; |
1512 | if (allfrag) | 1532 | if (allfrag) |
1513 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1533 | 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); | 1534 | dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1515 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1535 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
1516 | goto out; | 1536 | goto out; |
1517 | } | 1537 | } |
@@ -1537,7 +1557,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 | 1557 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
1538 | * and detecting PMTU increase will be automatically happened. | 1558 | * and detecting PMTU increase will be automatically happened. |
1539 | */ | 1559 | */ |
1540 | dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires); | 1560 | dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1541 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1561 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; |
1542 | 1562 | ||
1543 | ip6_ins_rt(nrt); | 1563 | ip6_ins_rt(nrt); |
@@ -1552,7 +1572,8 @@ out: | |||
1552 | 1572 | ||
1553 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1573 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) |
1554 | { | 1574 | { |
1555 | struct rt6_info *rt = ip6_dst_alloc(); | 1575 | struct net *net = ort->rt6i_dev->nd_net; |
1576 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1556 | 1577 | ||
1557 | if (rt) { | 1578 | if (rt) { |
1558 | rt->u.dst.input = ort->u.dst.input; | 1579 | rt->u.dst.input = ort->u.dst.input; |
@@ -1583,14 +1604,15 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1583 | } | 1604 | } |
1584 | 1605 | ||
1585 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1606 | #ifdef CONFIG_IPV6_ROUTE_INFO |
1586 | static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, | 1607 | static struct rt6_info *rt6_get_route_info(struct net *net, |
1608 | struct in6_addr *prefix, int prefixlen, | ||
1587 | struct in6_addr *gwaddr, int ifindex) | 1609 | struct in6_addr *gwaddr, int ifindex) |
1588 | { | 1610 | { |
1589 | struct fib6_node *fn; | 1611 | struct fib6_node *fn; |
1590 | struct rt6_info *rt = NULL; | 1612 | struct rt6_info *rt = NULL; |
1591 | struct fib6_table *table; | 1613 | struct fib6_table *table; |
1592 | 1614 | ||
1593 | table = fib6_get_table(RT6_TABLE_INFO); | 1615 | table = fib6_get_table(net, RT6_TABLE_INFO); |
1594 | if (table == NULL) | 1616 | if (table == NULL) |
1595 | return NULL; | 1617 | return NULL; |
1596 | 1618 | ||
@@ -1614,7 +1636,8 @@ out: | |||
1614 | return rt; | 1636 | return rt; |
1615 | } | 1637 | } |
1616 | 1638 | ||
1617 | static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, | 1639 | static struct rt6_info *rt6_add_route_info(struct net *net, |
1640 | struct in6_addr *prefix, int prefixlen, | ||
1618 | struct in6_addr *gwaddr, int ifindex, | 1641 | struct in6_addr *gwaddr, int ifindex, |
1619 | unsigned pref) | 1642 | unsigned pref) |
1620 | { | 1643 | { |
@@ -1625,6 +1648,9 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle | |||
1625 | .fc_dst_len = prefixlen, | 1648 | .fc_dst_len = prefixlen, |
1626 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | | 1649 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | |
1627 | RTF_UP | RTF_PREF(pref), | 1650 | RTF_UP | RTF_PREF(pref), |
1651 | .fc_nlinfo.pid = 0, | ||
1652 | .fc_nlinfo.nlh = NULL, | ||
1653 | .fc_nlinfo.nl_net = net, | ||
1628 | }; | 1654 | }; |
1629 | 1655 | ||
1630 | ipv6_addr_copy(&cfg.fc_dst, prefix); | 1656 | ipv6_addr_copy(&cfg.fc_dst, prefix); |
@@ -1636,7 +1662,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle | |||
1636 | 1662 | ||
1637 | ip6_route_add(&cfg); | 1663 | ip6_route_add(&cfg); |
1638 | 1664 | ||
1639 | return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); | 1665 | return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex); |
1640 | } | 1666 | } |
1641 | #endif | 1667 | #endif |
1642 | 1668 | ||
@@ -1645,7 +1671,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1645 | struct rt6_info *rt; | 1671 | struct rt6_info *rt; |
1646 | struct fib6_table *table; | 1672 | struct fib6_table *table; |
1647 | 1673 | ||
1648 | table = fib6_get_table(RT6_TABLE_DFLT); | 1674 | table = fib6_get_table(dev->nd_net, RT6_TABLE_DFLT); |
1649 | if (table == NULL) | 1675 | if (table == NULL) |
1650 | return NULL; | 1676 | return NULL; |
1651 | 1677 | ||
@@ -1674,6 +1700,9 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1674 | .fc_ifindex = dev->ifindex, | 1700 | .fc_ifindex = dev->ifindex, |
1675 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | | 1701 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | |
1676 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), | 1702 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), |
1703 | .fc_nlinfo.pid = 0, | ||
1704 | .fc_nlinfo.nlh = NULL, | ||
1705 | .fc_nlinfo.nl_net = dev->nd_net, | ||
1677 | }; | 1706 | }; |
1678 | 1707 | ||
1679 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1708 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); |
@@ -1683,13 +1712,13 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1683 | return rt6_get_dflt_router(gwaddr, dev); | 1712 | return rt6_get_dflt_router(gwaddr, dev); |
1684 | } | 1713 | } |
1685 | 1714 | ||
1686 | void rt6_purge_dflt_routers(void) | 1715 | void rt6_purge_dflt_routers(struct net *net) |
1687 | { | 1716 | { |
1688 | struct rt6_info *rt; | 1717 | struct rt6_info *rt; |
1689 | struct fib6_table *table; | 1718 | struct fib6_table *table; |
1690 | 1719 | ||
1691 | /* NOTE: Keep consistent with rt6_get_dflt_router */ | 1720 | /* NOTE: Keep consistent with rt6_get_dflt_router */ |
1692 | table = fib6_get_table(RT6_TABLE_DFLT); | 1721 | table = fib6_get_table(net, RT6_TABLE_DFLT); |
1693 | if (table == NULL) | 1722 | if (table == NULL) |
1694 | return; | 1723 | return; |
1695 | 1724 | ||
@@ -1706,7 +1735,8 @@ restart: | |||
1706 | read_unlock_bh(&table->tb6_lock); | 1735 | read_unlock_bh(&table->tb6_lock); |
1707 | } | 1736 | } |
1708 | 1737 | ||
1709 | static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, | 1738 | static void rtmsg_to_fib6_config(struct net *net, |
1739 | struct in6_rtmsg *rtmsg, | ||
1710 | struct fib6_config *cfg) | 1740 | struct fib6_config *cfg) |
1711 | { | 1741 | { |
1712 | memset(cfg, 0, sizeof(*cfg)); | 1742 | memset(cfg, 0, sizeof(*cfg)); |
@@ -1719,14 +1749,14 @@ static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, | |||
1719 | cfg->fc_src_len = rtmsg->rtmsg_src_len; | 1749 | cfg->fc_src_len = rtmsg->rtmsg_src_len; |
1720 | cfg->fc_flags = rtmsg->rtmsg_flags; | 1750 | cfg->fc_flags = rtmsg->rtmsg_flags; |
1721 | 1751 | ||
1722 | cfg->fc_nlinfo.nl_net = &init_net; | 1752 | cfg->fc_nlinfo.nl_net = net; |
1723 | 1753 | ||
1724 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); | 1754 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); |
1725 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); | 1755 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); |
1726 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); | 1756 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); |
1727 | } | 1757 | } |
1728 | 1758 | ||
1729 | int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | 1759 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
1730 | { | 1760 | { |
1731 | struct fib6_config cfg; | 1761 | struct fib6_config cfg; |
1732 | struct in6_rtmsg rtmsg; | 1762 | struct in6_rtmsg rtmsg; |
@@ -1742,7 +1772,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1742 | if (err) | 1772 | if (err) |
1743 | return -EFAULT; | 1773 | return -EFAULT; |
1744 | 1774 | ||
1745 | rtmsg_to_fib6_config(&rtmsg, &cfg); | 1775 | rtmsg_to_fib6_config(net, &rtmsg, &cfg); |
1746 | 1776 | ||
1747 | rtnl_lock(); | 1777 | rtnl_lock(); |
1748 | switch (cmd) { | 1778 | switch (cmd) { |
@@ -1821,21 +1851,22 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1821 | const struct in6_addr *addr, | 1851 | const struct in6_addr *addr, |
1822 | int anycast) | 1852 | int anycast) |
1823 | { | 1853 | { |
1824 | struct rt6_info *rt = ip6_dst_alloc(); | 1854 | struct net *net = idev->dev->nd_net; |
1855 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1825 | 1856 | ||
1826 | if (rt == NULL) | 1857 | if (rt == NULL) |
1827 | return ERR_PTR(-ENOMEM); | 1858 | return ERR_PTR(-ENOMEM); |
1828 | 1859 | ||
1829 | dev_hold(init_net.loopback_dev); | 1860 | dev_hold(net->loopback_dev); |
1830 | in6_dev_hold(idev); | 1861 | in6_dev_hold(idev); |
1831 | 1862 | ||
1832 | rt->u.dst.flags = DST_HOST; | 1863 | rt->u.dst.flags = DST_HOST; |
1833 | rt->u.dst.input = ip6_input; | 1864 | rt->u.dst.input = ip6_input; |
1834 | rt->u.dst.output = ip6_output; | 1865 | rt->u.dst.output = ip6_output; |
1835 | rt->rt6i_dev = init_net.loopback_dev; | 1866 | rt->rt6i_dev = net->loopback_dev; |
1836 | rt->rt6i_idev = idev; | 1867 | rt->rt6i_idev = idev; |
1837 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1868 | 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)); | 1869 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
1839 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1870 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; |
1840 | rt->u.dst.obsolete = -1; | 1871 | rt->u.dst.obsolete = -1; |
1841 | 1872 | ||
@@ -1852,26 +1883,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1852 | 1883 | ||
1853 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1884 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
1854 | rt->rt6i_dst.plen = 128; | 1885 | rt->rt6i_dst.plen = 128; |
1855 | rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL); | 1886 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
1856 | 1887 | ||
1857 | atomic_set(&rt->u.dst.__refcnt, 1); | 1888 | atomic_set(&rt->u.dst.__refcnt, 1); |
1858 | 1889 | ||
1859 | return rt; | 1890 | return rt; |
1860 | } | 1891 | } |
1861 | 1892 | ||
1893 | struct arg_dev_net { | ||
1894 | struct net_device *dev; | ||
1895 | struct net *net; | ||
1896 | }; | ||
1897 | |||
1862 | static int fib6_ifdown(struct rt6_info *rt, void *arg) | 1898 | static int fib6_ifdown(struct rt6_info *rt, void *arg) |
1863 | { | 1899 | { |
1864 | if (((void*)rt->rt6i_dev == arg || arg == NULL) && | 1900 | struct net_device *dev = ((struct arg_dev_net *)arg)->dev; |
1865 | rt != &ip6_null_entry) { | 1901 | struct net *net = ((struct arg_dev_net *)arg)->net; |
1902 | |||
1903 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | ||
1904 | rt != net->ipv6.ip6_null_entry) { | ||
1866 | RT6_TRACE("deleted by ifdown %p\n", rt); | 1905 | RT6_TRACE("deleted by ifdown %p\n", rt); |
1867 | return -1; | 1906 | return -1; |
1868 | } | 1907 | } |
1869 | return 0; | 1908 | return 0; |
1870 | } | 1909 | } |
1871 | 1910 | ||
1872 | void rt6_ifdown(struct net_device *dev) | 1911 | void rt6_ifdown(struct net *net, struct net_device *dev) |
1873 | { | 1912 | { |
1874 | fib6_clean_all(fib6_ifdown, 0, dev); | 1913 | struct arg_dev_net adn = { |
1914 | .dev = dev, | ||
1915 | .net = net, | ||
1916 | }; | ||
1917 | |||
1918 | fib6_clean_all(net, fib6_ifdown, 0, &adn); | ||
1875 | } | 1919 | } |
1876 | 1920 | ||
1877 | struct rt6_mtu_change_arg | 1921 | struct rt6_mtu_change_arg |
@@ -1884,6 +1928,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
1884 | { | 1928 | { |
1885 | struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; | 1929 | struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; |
1886 | struct inet6_dev *idev; | 1930 | struct inet6_dev *idev; |
1931 | struct net *net = arg->dev->nd_net; | ||
1887 | 1932 | ||
1888 | /* In IPv6 pmtu discovery is not optional, | 1933 | /* In IPv6 pmtu discovery is not optional, |
1889 | so that RTAX_MTU lock cannot disable it. | 1934 | so that RTAX_MTU lock cannot disable it. |
@@ -1915,7 +1960,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
1915 | (dst_mtu(&rt->u.dst) < arg->mtu && | 1960 | (dst_mtu(&rt->u.dst) < arg->mtu && |
1916 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { | 1961 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { |
1917 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; | 1962 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; |
1918 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu); | 1963 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); |
1919 | } | 1964 | } |
1920 | return 0; | 1965 | return 0; |
1921 | } | 1966 | } |
@@ -1927,7 +1972,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu) | |||
1927 | .mtu = mtu, | 1972 | .mtu = mtu, |
1928 | }; | 1973 | }; |
1929 | 1974 | ||
1930 | fib6_clean_all(rt6_mtu_change_route, 0, &arg); | 1975 | fib6_clean_all(dev->nd_net, rt6_mtu_change_route, 0, &arg); |
1931 | } | 1976 | } |
1932 | 1977 | ||
1933 | static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { | 1978 | static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { |
@@ -2010,13 +2055,9 @@ errout: | |||
2010 | 2055 | ||
2011 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2056 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2012 | { | 2057 | { |
2013 | struct net *net = skb->sk->sk_net; | ||
2014 | struct fib6_config cfg; | 2058 | struct fib6_config cfg; |
2015 | int err; | 2059 | int err; |
2016 | 2060 | ||
2017 | if (net != &init_net) | ||
2018 | return -EINVAL; | ||
2019 | |||
2020 | err = rtm_to_fib6_config(skb, nlh, &cfg); | 2061 | err = rtm_to_fib6_config(skb, nlh, &cfg); |
2021 | if (err < 0) | 2062 | if (err < 0) |
2022 | return err; | 2063 | return err; |
@@ -2026,13 +2067,9 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a | |||
2026 | 2067 | ||
2027 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2068 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2028 | { | 2069 | { |
2029 | struct net *net = skb->sk->sk_net; | ||
2030 | struct fib6_config cfg; | 2070 | struct fib6_config cfg; |
2031 | int err; | 2071 | int err; |
2032 | 2072 | ||
2033 | if (net != &init_net) | ||
2034 | return -EINVAL; | ||
2035 | |||
2036 | err = rtm_to_fib6_config(skb, nlh, &cfg); | 2073 | err = rtm_to_fib6_config(skb, nlh, &cfg); |
2037 | if (err < 0) | 2074 | if (err < 0) |
2038 | return err; | 2075 | return err; |
@@ -2122,7 +2159,8 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2122 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2159 | NLA_PUT_U32(skb, RTA_IIF, iif); |
2123 | else if (dst) { | 2160 | else if (dst) { |
2124 | struct in6_addr saddr_buf; | 2161 | struct in6_addr saddr_buf; |
2125 | if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) | 2162 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, |
2163 | dst, &saddr_buf) == 0) | ||
2126 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2164 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2127 | } | 2165 | } |
2128 | 2166 | ||
@@ -2175,9 +2213,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2175 | struct flowi fl; | 2213 | struct flowi fl; |
2176 | int err, iif = 0; | 2214 | int err, iif = 0; |
2177 | 2215 | ||
2178 | if (net != &init_net) | ||
2179 | return -EINVAL; | ||
2180 | |||
2181 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); | 2216 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); |
2182 | if (err < 0) | 2217 | if (err < 0) |
2183 | goto errout; | 2218 | goto errout; |
@@ -2207,7 +2242,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2207 | 2242 | ||
2208 | if (iif) { | 2243 | if (iif) { |
2209 | struct net_device *dev; | 2244 | struct net_device *dev; |
2210 | dev = __dev_get_by_index(&init_net, iif); | 2245 | dev = __dev_get_by_index(net, iif); |
2211 | if (!dev) { | 2246 | if (!dev) { |
2212 | err = -ENODEV; | 2247 | err = -ENODEV; |
2213 | goto errout; | 2248 | goto errout; |
@@ -2226,7 +2261,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2226 | skb_reset_mac_header(skb); | 2261 | skb_reset_mac_header(skb); |
2227 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2262 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2228 | 2263 | ||
2229 | rt = (struct rt6_info*) ip6_route_output(NULL, &fl); | 2264 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); |
2230 | skb->dst = &rt->u.dst; | 2265 | skb->dst = &rt->u.dst; |
2231 | 2266 | ||
2232 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2267 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
@@ -2237,7 +2272,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2237 | goto errout; | 2272 | goto errout; |
2238 | } | 2273 | } |
2239 | 2274 | ||
2240 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 2275 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
2241 | errout: | 2276 | errout: |
2242 | return err; | 2277 | return err; |
2243 | } | 2278 | } |
@@ -2245,6 +2280,7 @@ errout: | |||
2245 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | 2280 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) |
2246 | { | 2281 | { |
2247 | struct sk_buff *skb; | 2282 | struct sk_buff *skb; |
2283 | struct net *net = info->nl_net; | ||
2248 | u32 seq; | 2284 | u32 seq; |
2249 | int err; | 2285 | int err; |
2250 | 2286 | ||
@@ -2263,11 +2299,31 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2263 | kfree_skb(skb); | 2299 | kfree_skb(skb); |
2264 | goto errout; | 2300 | goto errout; |
2265 | } | 2301 | } |
2266 | err = rtnl_notify(skb, &init_net, info->pid, | 2302 | err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, |
2267 | RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any()); | 2303 | info->nlh, gfp_any()); |
2268 | errout: | 2304 | errout: |
2269 | if (err < 0) | 2305 | if (err < 0) |
2270 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err); | 2306 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
2307 | } | ||
2308 | |||
2309 | static int ip6_route_dev_notify(struct notifier_block *this, | ||
2310 | unsigned long event, void *data) | ||
2311 | { | ||
2312 | struct net_device *dev = (struct net_device *)data; | ||
2313 | struct net *net = dev->nd_net; | ||
2314 | |||
2315 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | ||
2316 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | ||
2317 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | ||
2318 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2319 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | ||
2320 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | ||
2321 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | ||
2322 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | ||
2323 | #endif | ||
2324 | } | ||
2325 | |||
2326 | return NOTIFY_OK; | ||
2271 | } | 2327 | } |
2272 | 2328 | ||
2273 | /* | 2329 | /* |
@@ -2316,13 +2372,25 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2316 | 2372 | ||
2317 | static int ipv6_route_show(struct seq_file *m, void *v) | 2373 | static int ipv6_route_show(struct seq_file *m, void *v) |
2318 | { | 2374 | { |
2319 | fib6_clean_all(rt6_info_route, 0, m); | 2375 | struct net *net = (struct net *)m->private; |
2376 | fib6_clean_all(net, rt6_info_route, 0, m); | ||
2320 | return 0; | 2377 | return 0; |
2321 | } | 2378 | } |
2322 | 2379 | ||
2323 | static int ipv6_route_open(struct inode *inode, struct file *file) | 2380 | static int ipv6_route_open(struct inode *inode, struct file *file) |
2324 | { | 2381 | { |
2325 | return single_open(file, ipv6_route_show, NULL); | 2382 | struct net *net = get_proc_net(inode); |
2383 | if (!net) | ||
2384 | return -ENXIO; | ||
2385 | return single_open(file, ipv6_route_show, net); | ||
2386 | } | ||
2387 | |||
2388 | static int ipv6_route_release(struct inode *inode, struct file *file) | ||
2389 | { | ||
2390 | struct seq_file *seq = file->private_data; | ||
2391 | struct net *net = seq->private; | ||
2392 | put_net(net); | ||
2393 | return single_release(inode, file); | ||
2326 | } | 2394 | } |
2327 | 2395 | ||
2328 | static const struct file_operations ipv6_route_proc_fops = { | 2396 | static const struct file_operations ipv6_route_proc_fops = { |
@@ -2330,24 +2398,36 @@ static const struct file_operations ipv6_route_proc_fops = { | |||
2330 | .open = ipv6_route_open, | 2398 | .open = ipv6_route_open, |
2331 | .read = seq_read, | 2399 | .read = seq_read, |
2332 | .llseek = seq_lseek, | 2400 | .llseek = seq_lseek, |
2333 | .release = single_release, | 2401 | .release = ipv6_route_release, |
2334 | }; | 2402 | }; |
2335 | 2403 | ||
2336 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) | 2404 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) |
2337 | { | 2405 | { |
2406 | struct net *net = (struct net *)seq->private; | ||
2338 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", | 2407 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", |
2339 | rt6_stats.fib_nodes, rt6_stats.fib_route_nodes, | 2408 | net->ipv6.rt6_stats->fib_nodes, |
2340 | rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries, | 2409 | net->ipv6.rt6_stats->fib_route_nodes, |
2341 | rt6_stats.fib_rt_cache, | 2410 | net->ipv6.rt6_stats->fib_rt_alloc, |
2342 | atomic_read(&ip6_dst_ops.entries), | 2411 | net->ipv6.rt6_stats->fib_rt_entries, |
2343 | rt6_stats.fib_discarded_routes); | 2412 | net->ipv6.rt6_stats->fib_rt_cache, |
2413 | atomic_read(&net->ipv6.ip6_dst_ops->entries), | ||
2414 | net->ipv6.rt6_stats->fib_discarded_routes); | ||
2344 | 2415 | ||
2345 | return 0; | 2416 | return 0; |
2346 | } | 2417 | } |
2347 | 2418 | ||
2348 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) | 2419 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) |
2349 | { | 2420 | { |
2350 | return single_open(file, rt6_stats_seq_show, NULL); | 2421 | struct net *net = get_proc_net(inode); |
2422 | return single_open(file, rt6_stats_seq_show, net); | ||
2423 | } | ||
2424 | |||
2425 | static int rt6_stats_seq_release(struct inode *inode, struct file *file) | ||
2426 | { | ||
2427 | struct seq_file *seq = file->private_data; | ||
2428 | struct net *net = (struct net *)seq->private; | ||
2429 | put_net(net); | ||
2430 | return single_release(inode, file); | ||
2351 | } | 2431 | } |
2352 | 2432 | ||
2353 | static const struct file_operations rt6_stats_seq_fops = { | 2433 | static const struct file_operations rt6_stats_seq_fops = { |
@@ -2355,42 +2435,8 @@ static const struct file_operations rt6_stats_seq_fops = { | |||
2355 | .open = rt6_stats_seq_open, | 2435 | .open = rt6_stats_seq_open, |
2356 | .read = seq_read, | 2436 | .read = seq_read, |
2357 | .llseek = seq_lseek, | 2437 | .llseek = seq_lseek, |
2358 | .release = single_release, | 2438 | .release = rt6_stats_seq_release, |
2359 | }; | 2439 | }; |
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 */ | 2440 | #endif /* CONFIG_PROC_FS */ |
2395 | 2441 | ||
2396 | #ifdef CONFIG_SYSCTL | 2442 | #ifdef CONFIG_SYSCTL |
@@ -2399,10 +2445,11 @@ static | |||
2399 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, | 2445 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, |
2400 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2446 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2401 | { | 2447 | { |
2402 | int delay = init_net.ipv6.sysctl.flush_delay; | 2448 | struct net *net = current->nsproxy->net_ns; |
2449 | int delay = net->ipv6.sysctl.flush_delay; | ||
2403 | if (write) { | 2450 | if (write) { |
2404 | proc_dointvec(ctl, write, filp, buffer, lenp, ppos); | 2451 | proc_dointvec(ctl, write, filp, buffer, lenp, ppos); |
2405 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay); | 2452 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net); |
2406 | return 0; | 2453 | return 0; |
2407 | } else | 2454 | } else |
2408 | return -EINVAL; | 2455 | return -EINVAL; |
@@ -2419,7 +2466,7 @@ ctl_table ipv6_route_table_template[] = { | |||
2419 | { | 2466 | { |
2420 | .ctl_name = NET_IPV6_ROUTE_GC_THRESH, | 2467 | .ctl_name = NET_IPV6_ROUTE_GC_THRESH, |
2421 | .procname = "gc_thresh", | 2468 | .procname = "gc_thresh", |
2422 | .data = &ip6_dst_ops.gc_thresh, | 2469 | .data = &ip6_dst_ops_template.gc_thresh, |
2423 | .maxlen = sizeof(int), | 2470 | .maxlen = sizeof(int), |
2424 | .mode = 0644, | 2471 | .mode = 0644, |
2425 | .proc_handler = &proc_dointvec, | 2472 | .proc_handler = &proc_dointvec, |
@@ -2505,33 +2552,141 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) | |||
2505 | table = kmemdup(ipv6_route_table_template, | 2552 | table = kmemdup(ipv6_route_table_template, |
2506 | sizeof(ipv6_route_table_template), | 2553 | sizeof(ipv6_route_table_template), |
2507 | GFP_KERNEL); | 2554 | GFP_KERNEL); |
2555 | |||
2556 | if (table) { | ||
2557 | table[0].data = &net->ipv6.sysctl.flush_delay; | ||
2558 | table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh; | ||
2559 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; | ||
2560 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | ||
2561 | table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
2562 | table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval; | ||
2563 | table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
2564 | table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; | ||
2565 | table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; | ||
2566 | } | ||
2567 | |||
2508 | return table; | 2568 | return table; |
2509 | } | 2569 | } |
2510 | #endif | 2570 | #endif |
2511 | 2571 | ||
2572 | static int ip6_route_net_init(struct net *net) | ||
2573 | { | ||
2574 | int ret = 0; | ||
2575 | |||
2576 | ret = -ENOMEM; | ||
2577 | net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template, | ||
2578 | sizeof(*net->ipv6.ip6_dst_ops), | ||
2579 | GFP_KERNEL); | ||
2580 | if (!net->ipv6.ip6_dst_ops) | ||
2581 | goto out; | ||
2582 | net->ipv6.ip6_dst_ops->dst_net = net; | ||
2583 | |||
2584 | net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, | ||
2585 | sizeof(*net->ipv6.ip6_null_entry), | ||
2586 | GFP_KERNEL); | ||
2587 | if (!net->ipv6.ip6_null_entry) | ||
2588 | goto out_ip6_dst_ops; | ||
2589 | net->ipv6.ip6_null_entry->u.dst.path = | ||
2590 | (struct dst_entry *)net->ipv6.ip6_null_entry; | ||
2591 | net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2592 | |||
2593 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2594 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | ||
2595 | sizeof(*net->ipv6.ip6_prohibit_entry), | ||
2596 | GFP_KERNEL); | ||
2597 | if (!net->ipv6.ip6_prohibit_entry) { | ||
2598 | kfree(net->ipv6.ip6_null_entry); | ||
2599 | goto out; | ||
2600 | } | ||
2601 | net->ipv6.ip6_prohibit_entry->u.dst.path = | ||
2602 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | ||
2603 | net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2604 | |||
2605 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | ||
2606 | sizeof(*net->ipv6.ip6_blk_hole_entry), | ||
2607 | GFP_KERNEL); | ||
2608 | if (!net->ipv6.ip6_blk_hole_entry) { | ||
2609 | kfree(net->ipv6.ip6_null_entry); | ||
2610 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2611 | goto out; | ||
2612 | } | ||
2613 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | ||
2614 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | ||
2615 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2616 | #endif | ||
2617 | |||
2618 | #ifdef CONFIG_PROC_FS | ||
2619 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2620 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2621 | #endif | ||
2622 | net->ipv6.ip6_rt_gc_expire = 30*HZ; | ||
2623 | |||
2624 | ret = 0; | ||
2625 | out: | ||
2626 | return ret; | ||
2627 | |||
2628 | out_ip6_dst_ops: | ||
2629 | kfree(net->ipv6.ip6_dst_ops); | ||
2630 | goto out; | ||
2631 | } | ||
2632 | |||
2633 | static void ip6_route_net_exit(struct net *net) | ||
2634 | { | ||
2635 | #ifdef CONFIG_PROC_FS | ||
2636 | proc_net_remove(net, "ipv6_route"); | ||
2637 | proc_net_remove(net, "rt6_stats"); | ||
2638 | #endif | ||
2639 | kfree(net->ipv6.ip6_null_entry); | ||
2640 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2641 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2642 | kfree(net->ipv6.ip6_blk_hole_entry); | ||
2643 | #endif | ||
2644 | kfree(net->ipv6.ip6_dst_ops); | ||
2645 | } | ||
2646 | |||
2647 | static struct pernet_operations ip6_route_net_ops = { | ||
2648 | .init = ip6_route_net_init, | ||
2649 | .exit = ip6_route_net_exit, | ||
2650 | }; | ||
2651 | |||
2652 | static struct notifier_block ip6_route_dev_notifier = { | ||
2653 | .notifier_call = ip6_route_dev_notify, | ||
2654 | .priority = 0, | ||
2655 | }; | ||
2656 | |||
2512 | int __init ip6_route_init(void) | 2657 | int __init ip6_route_init(void) |
2513 | { | 2658 | { |
2514 | int ret; | 2659 | int ret; |
2515 | 2660 | ||
2516 | ip6_dst_ops.kmem_cachep = | 2661 | ret = -ENOMEM; |
2662 | ip6_dst_ops_template.kmem_cachep = | ||
2517 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, | 2663 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, |
2518 | SLAB_HWCACHE_ALIGN, NULL); | 2664 | SLAB_HWCACHE_ALIGN, NULL); |
2519 | if (!ip6_dst_ops.kmem_cachep) | 2665 | if (!ip6_dst_ops_template.kmem_cachep) |
2520 | return -ENOMEM; | 2666 | goto out;; |
2521 | 2667 | ||
2522 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; | 2668 | ret = register_pernet_subsys(&ip6_route_net_ops); |
2523 | |||
2524 | ret = fib6_init(); | ||
2525 | if (ret) | 2669 | if (ret) |
2526 | goto out_kmem_cache; | 2670 | goto out_kmem_cache; |
2527 | 2671 | ||
2528 | ret = ipv6_route_proc_init(&init_net); | 2672 | /* Registering of the loopback is done before this portion of code, |
2673 | * the loopback reference in rt6_info will not be taken, do it | ||
2674 | * manually for init_net */ | ||
2675 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | ||
2676 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2677 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2678 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | ||
2679 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2680 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | ||
2681 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2682 | #endif | ||
2683 | ret = fib6_init(); | ||
2529 | if (ret) | 2684 | if (ret) |
2530 | goto out_fib6_init; | 2685 | goto out_register_subsys; |
2531 | 2686 | ||
2532 | ret = xfrm6_init(); | 2687 | ret = xfrm6_init(); |
2533 | if (ret) | 2688 | if (ret) |
2534 | goto out_proc_init; | 2689 | goto out_fib6_init; |
2535 | 2690 | ||
2536 | ret = fib6_rules_init(); | 2691 | ret = fib6_rules_init(); |
2537 | if (ret) | 2692 | if (ret) |
@@ -2543,7 +2698,10 @@ int __init ip6_route_init(void) | |||
2543 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2698 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) |
2544 | goto fib6_rules_init; | 2699 | goto fib6_rules_init; |
2545 | 2700 | ||
2546 | ret = 0; | 2701 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
2702 | if (ret) | ||
2703 | goto fib6_rules_init; | ||
2704 | |||
2547 | out: | 2705 | out: |
2548 | return ret; | 2706 | return ret; |
2549 | 2707 | ||
@@ -2551,22 +2709,21 @@ fib6_rules_init: | |||
2551 | fib6_rules_cleanup(); | 2709 | fib6_rules_cleanup(); |
2552 | xfrm6_init: | 2710 | xfrm6_init: |
2553 | xfrm6_fini(); | 2711 | xfrm6_fini(); |
2554 | out_proc_init: | ||
2555 | ipv6_route_proc_fini(&init_net); | ||
2556 | out_fib6_init: | 2712 | out_fib6_init: |
2557 | rt6_ifdown(NULL); | ||
2558 | fib6_gc_cleanup(); | 2713 | fib6_gc_cleanup(); |
2714 | out_register_subsys: | ||
2715 | unregister_pernet_subsys(&ip6_route_net_ops); | ||
2559 | out_kmem_cache: | 2716 | out_kmem_cache: |
2560 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2717 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); |
2561 | goto out; | 2718 | goto out; |
2562 | } | 2719 | } |
2563 | 2720 | ||
2564 | void ip6_route_cleanup(void) | 2721 | void ip6_route_cleanup(void) |
2565 | { | 2722 | { |
2723 | unregister_netdevice_notifier(&ip6_route_dev_notifier); | ||
2566 | fib6_rules_cleanup(); | 2724 | fib6_rules_cleanup(); |
2567 | ipv6_route_proc_fini(&init_net); | ||
2568 | xfrm6_fini(); | 2725 | xfrm6_fini(); |
2569 | rt6_ifdown(NULL); | ||
2570 | fib6_gc_cleanup(); | 2726 | fib6_gc_cleanup(); |
2571 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2727 | unregister_pernet_subsys(&ip6_route_net_ops); |
2728 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); | ||
2572 | } | 2729 | } |
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..827c5aa7524c --- /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-3+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..8dd72966ff78 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, |
@@ -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 = skb->dst->dev->nd_net; | ||
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 = skb->dev->nd_net; | ||
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 | } |
@@ -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) |
@@ -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..5f5d1218c34e 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, |
@@ -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 (s->sk_net != sk->sk_net) | ||
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) { |
@@ -986,13 +989,13 @@ static struct udp_seq_afinfo udp6_seq_afinfo = { | |||
986 | .seq_fops = &udp6_seq_fops, | 989 | .seq_fops = &udp6_seq_fops, |
987 | }; | 990 | }; |
988 | 991 | ||
989 | int __init udp6_proc_init(void) | 992 | int udp6_proc_init(struct net *net) |
990 | { | 993 | { |
991 | return udp_proc_register(&udp6_seq_afinfo); | 994 | return udp_proc_register(net, &udp6_seq_afinfo); |
992 | } | 995 | } |
993 | 996 | ||
994 | void udp6_proc_exit(void) { | 997 | void udp6_proc_exit(struct net *net) { |
995 | udp_proc_unregister(&udp6_seq_afinfo); | 998 | udp_proc_unregister(net, &udp6_seq_afinfo); |
996 | } | 999 | } |
997 | #endif /* CONFIG_PROC_FS */ | 1000 | #endif /* CONFIG_PROC_FS */ |
998 | 1001 | ||
@@ -1021,6 +1024,7 @@ struct proto udpv6_prot = { | |||
1021 | .sysctl_wmem = &sysctl_udp_wmem_min, | 1024 | .sysctl_wmem = &sysctl_udp_wmem_min, |
1022 | .sysctl_rmem = &sysctl_udp_rmem_min, | 1025 | .sysctl_rmem = &sysctl_udp_rmem_min, |
1023 | .obj_size = sizeof(struct udp6_sock), | 1026 | .obj_size = sizeof(struct udp6_sock), |
1027 | .h.udp_hash = udp_hash, | ||
1024 | #ifdef CONFIG_COMPAT | 1028 | #ifdef CONFIG_COMPAT |
1025 | .compat_setsockopt = compat_udpv6_setsockopt, | 1029 | .compat_setsockopt = compat_udpv6_setsockopt, |
1026 | .compat_getsockopt = compat_udpv6_getsockopt, | 1030 | .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..93e52e0d57f2 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, |
@@ -115,11 +111,11 @@ static struct udp_seq_afinfo udplite6_seq_afinfo = { | |||
115 | 111 | ||
116 | int __init udplite6_proc_init(void) | 112 | int __init udplite6_proc_init(void) |
117 | { | 113 | { |
118 | return udp_proc_register(&udplite6_seq_afinfo); | 114 | return udp_proc_register(&init_net, &udplite6_seq_afinfo); |
119 | } | 115 | } |
120 | 116 | ||
121 | void udplite6_proc_exit(void) | 117 | void udplite6_proc_exit(void) |
122 | { | 118 | { |
123 | udp_proc_unregister(&udplite6_seq_afinfo); | 119 | udp_proc_unregister(&init_net, &udplite6_seq_afinfo); |
124 | } | 120 | } |
125 | #endif | 121 | #endif |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 7d20199ee1f3..e96dafdc7032 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, |
62 | (struct in6_addr *)&saddr->a6); | ||
62 | dst_release(dst); | 63 | dst_release(dst); |
63 | return 0; | 64 | return 0; |
64 | } | 65 | } |