diff options
Diffstat (limited to 'net/ipv6')
39 files changed, 4675 insertions, 1759 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 47263e45bacb..42814a2ec9d7 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # IPv6 as module will cause a CRASH if you try to unload it | 5 | # IPv6 as module will cause a CRASH if you try to unload it |
6 | config IPV6 | 6 | menuconfig IPV6 |
7 | tristate "The IPv6 protocol" | 7 | tristate "The IPv6 protocol" |
8 | default m | 8 | default m |
9 | ---help--- | 9 | ---help--- |
@@ -19,9 +19,10 @@ config IPV6 | |||
19 | To compile this protocol support as a module, choose M here: the | 19 | To compile this protocol support as a module, choose M here: the |
20 | module will be called ipv6. | 20 | module will be called ipv6. |
21 | 21 | ||
22 | if IPV6 | ||
23 | |||
22 | config IPV6_PRIVACY | 24 | config IPV6_PRIVACY |
23 | bool "IPv6: Privacy Extensions support" | 25 | bool "IPv6: Privacy Extensions support" |
24 | depends on IPV6 | ||
25 | ---help--- | 26 | ---help--- |
26 | Privacy Extensions for Stateless Address Autoconfiguration in IPv6 | 27 | Privacy Extensions for Stateless Address Autoconfiguration in IPv6 |
27 | support. With this option, additional periodically-alter | 28 | support. With this option, additional periodically-alter |
@@ -40,7 +41,6 @@ config IPV6_PRIVACY | |||
40 | 41 | ||
41 | config IPV6_ROUTER_PREF | 42 | config IPV6_ROUTER_PREF |
42 | bool "IPv6: Router Preference (RFC 4191) support" | 43 | bool "IPv6: Router Preference (RFC 4191) support" |
43 | depends on IPV6 | ||
44 | ---help--- | 44 | ---help--- |
45 | Router Preference is an optional extension to the Router | 45 | Router Preference is an optional extension to the Router |
46 | Advertisement message to improve the ability of hosts | 46 | Advertisement message to improve the ability of hosts |
@@ -59,7 +59,7 @@ config IPV6_ROUTE_INFO | |||
59 | 59 | ||
60 | config IPV6_OPTIMISTIC_DAD | 60 | config IPV6_OPTIMISTIC_DAD |
61 | bool "IPv6: Enable RFC 4429 Optimistic DAD (EXPERIMENTAL)" | 61 | bool "IPv6: Enable RFC 4429 Optimistic DAD (EXPERIMENTAL)" |
62 | depends on IPV6 && EXPERIMENTAL | 62 | depends on EXPERIMENTAL |
63 | ---help--- | 63 | ---help--- |
64 | This is experimental support for optimistic Duplicate | 64 | This is experimental support for optimistic Duplicate |
65 | Address Detection. It allows for autoconfigured addresses | 65 | Address Detection. It allows for autoconfigured addresses |
@@ -69,7 +69,6 @@ config IPV6_OPTIMISTIC_DAD | |||
69 | 69 | ||
70 | config INET6_AH | 70 | config INET6_AH |
71 | tristate "IPv6: AH transformation" | 71 | tristate "IPv6: AH transformation" |
72 | depends on IPV6 | ||
73 | select XFRM | 72 | select XFRM |
74 | select CRYPTO | 73 | select CRYPTO |
75 | select CRYPTO_HMAC | 74 | select CRYPTO_HMAC |
@@ -82,7 +81,6 @@ config INET6_AH | |||
82 | 81 | ||
83 | config INET6_ESP | 82 | config INET6_ESP |
84 | tristate "IPv6: ESP transformation" | 83 | tristate "IPv6: ESP transformation" |
85 | depends on IPV6 | ||
86 | select XFRM | 84 | select XFRM |
87 | select CRYPTO | 85 | select CRYPTO |
88 | select CRYPTO_AUTHENC | 86 | select CRYPTO_AUTHENC |
@@ -98,7 +96,6 @@ config INET6_ESP | |||
98 | 96 | ||
99 | config INET6_IPCOMP | 97 | config INET6_IPCOMP |
100 | tristate "IPv6: IPComp transformation" | 98 | tristate "IPv6: IPComp transformation" |
101 | depends on IPV6 | ||
102 | select XFRM | 99 | select XFRM |
103 | select INET6_XFRM_TUNNEL | 100 | select INET6_XFRM_TUNNEL |
104 | select CRYPTO | 101 | select CRYPTO |
@@ -111,7 +108,7 @@ config INET6_IPCOMP | |||
111 | 108 | ||
112 | config IPV6_MIP6 | 109 | config IPV6_MIP6 |
113 | tristate "IPv6: Mobility (EXPERIMENTAL)" | 110 | tristate "IPv6: Mobility (EXPERIMENTAL)" |
114 | depends on IPV6 && EXPERIMENTAL | 111 | depends on EXPERIMENTAL |
115 | select XFRM | 112 | select XFRM |
116 | ---help--- | 113 | ---help--- |
117 | Support for IPv6 Mobility described in RFC 3775. | 114 | Support for IPv6 Mobility described in RFC 3775. |
@@ -129,7 +126,6 @@ config INET6_TUNNEL | |||
129 | 126 | ||
130 | config INET6_XFRM_MODE_TRANSPORT | 127 | config INET6_XFRM_MODE_TRANSPORT |
131 | tristate "IPv6: IPsec transport mode" | 128 | tristate "IPv6: IPsec transport mode" |
132 | depends on IPV6 | ||
133 | default IPV6 | 129 | default IPV6 |
134 | select XFRM | 130 | select XFRM |
135 | ---help--- | 131 | ---help--- |
@@ -139,7 +135,6 @@ config INET6_XFRM_MODE_TRANSPORT | |||
139 | 135 | ||
140 | config INET6_XFRM_MODE_TUNNEL | 136 | config INET6_XFRM_MODE_TUNNEL |
141 | tristate "IPv6: IPsec tunnel mode" | 137 | tristate "IPv6: IPsec tunnel mode" |
142 | depends on IPV6 | ||
143 | default IPV6 | 138 | default IPV6 |
144 | select XFRM | 139 | select XFRM |
145 | ---help--- | 140 | ---help--- |
@@ -149,7 +144,6 @@ config INET6_XFRM_MODE_TUNNEL | |||
149 | 144 | ||
150 | config INET6_XFRM_MODE_BEET | 145 | config INET6_XFRM_MODE_BEET |
151 | tristate "IPv6: IPsec BEET mode" | 146 | tristate "IPv6: IPsec BEET mode" |
152 | depends on IPV6 | ||
153 | default IPV6 | 147 | default IPV6 |
154 | select XFRM | 148 | select XFRM |
155 | ---help--- | 149 | ---help--- |
@@ -159,15 +153,15 @@ config INET6_XFRM_MODE_BEET | |||
159 | 153 | ||
160 | config INET6_XFRM_MODE_ROUTEOPTIMIZATION | 154 | config INET6_XFRM_MODE_ROUTEOPTIMIZATION |
161 | tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" | 155 | tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" |
162 | depends on IPV6 && EXPERIMENTAL | 156 | depends on EXPERIMENTAL |
163 | select XFRM | 157 | select XFRM |
164 | ---help--- | 158 | ---help--- |
165 | Support for MIPv6 route optimization mode. | 159 | Support for MIPv6 route optimization mode. |
166 | 160 | ||
167 | config IPV6_SIT | 161 | config IPV6_SIT |
168 | tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)" | 162 | tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)" |
169 | depends on IPV6 | ||
170 | select INET_TUNNEL | 163 | select INET_TUNNEL |
164 | select IPV6_NDISC_NODETYPE | ||
171 | default y | 165 | default y |
172 | ---help--- | 166 | ---help--- |
173 | Tunneling means encapsulating data of one protocol type within | 167 | Tunneling means encapsulating data of one protocol type within |
@@ -178,10 +172,12 @@ config IPV6_SIT | |||
178 | 172 | ||
179 | Saying M here will produce a module called sit.ko. If unsure, say Y. | 173 | Saying M here will produce a module called sit.ko. If unsure, say Y. |
180 | 174 | ||
175 | config IPV6_NDISC_NODETYPE | ||
176 | bool | ||
177 | |||
181 | config IPV6_TUNNEL | 178 | config IPV6_TUNNEL |
182 | tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)" | 179 | tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)" |
183 | select INET6_TUNNEL | 180 | select INET6_TUNNEL |
184 | depends on IPV6 | ||
185 | ---help--- | 181 | ---help--- |
186 | Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in | 182 | Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in |
187 | RFC 2473. | 183 | RFC 2473. |
@@ -190,7 +186,7 @@ config IPV6_TUNNEL | |||
190 | 186 | ||
191 | config IPV6_MULTIPLE_TABLES | 187 | config IPV6_MULTIPLE_TABLES |
192 | bool "IPv6: Multiple Routing Tables" | 188 | bool "IPv6: Multiple Routing Tables" |
193 | depends on IPV6 && EXPERIMENTAL | 189 | depends on EXPERIMENTAL |
194 | select FIB_RULES | 190 | select FIB_RULES |
195 | ---help--- | 191 | ---help--- |
196 | Support multiple routing tables. | 192 | Support multiple routing tables. |
@@ -209,3 +205,18 @@ config IPV6_SUBTREES | |||
209 | 205 | ||
210 | If unsure, say N. | 206 | If unsure, say N. |
211 | 207 | ||
208 | config IPV6_MROUTE | ||
209 | bool "IPv6: multicast routing (EXPERIMENTAL)" | ||
210 | depends on IPV6 && EXPERIMENTAL | ||
211 | ---help--- | ||
212 | Experimental support for IPv6 multicast forwarding. | ||
213 | If unsure, say N. | ||
214 | |||
215 | config IPV6_PIMSM_V2 | ||
216 | bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)" | ||
217 | depends on IPV6_MROUTE | ||
218 | ---help--- | ||
219 | Support for IPv6 PIM multicast routing protocol PIM-SMv2. | ||
220 | If unsure, say N. | ||
221 | |||
222 | endif # IPV6 | ||
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 24f3aa0f2a35..686934acfac1 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -11,11 +11,14 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ | |||
11 | exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o | 11 | exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o |
12 | 12 | ||
13 | ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o | 13 | ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o |
14 | ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o | ||
15 | |||
14 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | 16 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ |
15 | xfrm6_output.o | 17 | xfrm6_output.o |
16 | ipv6-$(CONFIG_NETFILTER) += netfilter.o | 18 | ipv6-$(CONFIG_NETFILTER) += netfilter.o |
17 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o | 19 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o |
18 | ipv6-$(CONFIG_PROC_FS) += proc.o | 20 | ipv6-$(CONFIG_PROC_FS) += proc.o |
21 | ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o | ||
19 | 22 | ||
20 | ipv6-objs += $(ipv6-y) | 23 | ipv6-objs += $(ipv6-y) |
21 | 24 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e08955baedff..8a0fd4007bdb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -222,6 +222,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
222 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | 222 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ |
223 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | 223 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; |
224 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | 224 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; |
225 | const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; | ||
226 | const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; | ||
225 | 227 | ||
226 | /* Check if a valid qdisc is available */ | 228 | /* Check if a valid qdisc is available */ |
227 | static inline int addrconf_qdisc_ok(struct net_device *dev) | 229 | static inline int addrconf_qdisc_ok(struct net_device *dev) |
@@ -321,7 +323,6 @@ EXPORT_SYMBOL(in6_dev_finish_destroy); | |||
321 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | 323 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) |
322 | { | 324 | { |
323 | struct inet6_dev *ndev; | 325 | struct inet6_dev *ndev; |
324 | struct in6_addr maddr; | ||
325 | 326 | ||
326 | ASSERT_RTNL(); | 327 | ASSERT_RTNL(); |
327 | 328 | ||
@@ -335,7 +336,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
335 | 336 | ||
336 | rwlock_init(&ndev->lock); | 337 | rwlock_init(&ndev->lock); |
337 | ndev->dev = dev; | 338 | ndev->dev = dev; |
338 | memcpy(&ndev->cnf, dev->nd_net->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 339 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
339 | ndev->cnf.mtu6 = dev->mtu; | 340 | ndev->cnf.mtu6 = dev->mtu; |
340 | ndev->cnf.sysctl = NULL; | 341 | ndev->cnf.sysctl = NULL; |
341 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | 342 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); |
@@ -349,7 +350,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
349 | if (snmp6_alloc_dev(ndev) < 0) { | 350 | if (snmp6_alloc_dev(ndev) < 0) { |
350 | ADBG((KERN_WARNING | 351 | ADBG((KERN_WARNING |
351 | "%s(): cannot allocate memory for statistics; dev=%s.\n", | 352 | "%s(): cannot allocate memory for statistics; dev=%s.\n", |
352 | __FUNCTION__, dev->name)); | 353 | __func__, dev->name)); |
353 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 354 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
354 | ndev->dead = 1; | 355 | ndev->dead = 1; |
355 | in6_dev_finish_destroy(ndev); | 356 | in6_dev_finish_destroy(ndev); |
@@ -359,7 +360,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
359 | if (snmp6_register_dev(ndev) < 0) { | 360 | if (snmp6_register_dev(ndev) < 0) { |
360 | ADBG((KERN_WARNING | 361 | ADBG((KERN_WARNING |
361 | "%s(): cannot create /proc/net/dev_snmp6/%s\n", | 362 | "%s(): cannot create /proc/net/dev_snmp6/%s\n", |
362 | __FUNCTION__, dev->name)); | 363 | __func__, dev->name)); |
363 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 364 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
364 | ndev->dead = 1; | 365 | ndev->dead = 1; |
365 | in6_dev_finish_destroy(ndev); | 366 | in6_dev_finish_destroy(ndev); |
@@ -407,8 +408,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
407 | rcu_assign_pointer(dev->ip6_ptr, ndev); | 408 | rcu_assign_pointer(dev->ip6_ptr, ndev); |
408 | 409 | ||
409 | /* Join all-node multicast group */ | 410 | /* Join all-node multicast group */ |
410 | ipv6_addr_all_nodes(&maddr); | 411 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); |
411 | ipv6_dev_mc_inc(dev, &maddr); | ||
412 | 412 | ||
413 | return ndev; | 413 | return ndev; |
414 | } | 414 | } |
@@ -434,18 +434,15 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
434 | { | 434 | { |
435 | struct net_device *dev; | 435 | struct net_device *dev; |
436 | struct inet6_ifaddr *ifa; | 436 | struct inet6_ifaddr *ifa; |
437 | struct in6_addr addr; | ||
438 | 437 | ||
439 | if (!idev) | 438 | if (!idev) |
440 | return; | 439 | return; |
441 | dev = idev->dev; | 440 | dev = idev->dev; |
442 | if (dev && (dev->flags & IFF_MULTICAST)) { | 441 | if (dev && (dev->flags & IFF_MULTICAST)) { |
443 | ipv6_addr_all_routers(&addr); | ||
444 | |||
445 | if (idev->cnf.forwarding) | 442 | if (idev->cnf.forwarding) |
446 | ipv6_dev_mc_inc(dev, &addr); | 443 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); |
447 | else | 444 | else |
448 | ipv6_dev_mc_dec(dev, &addr); | 445 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
449 | } | 446 | } |
450 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 447 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { |
451 | if (ifa->flags&IFA_F_TENTATIVE) | 448 | if (ifa->flags&IFA_F_TENTATIVE) |
@@ -494,7 +491,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
494 | dev_forward_change((struct inet6_dev *)table->extra1); | 491 | dev_forward_change((struct inet6_dev *)table->extra1); |
495 | 492 | ||
496 | if (*p) | 493 | if (*p) |
497 | rt6_purge_dflt_routers(); | 494 | rt6_purge_dflt_routers(net); |
498 | } | 495 | } |
499 | #endif | 496 | #endif |
500 | 497 | ||
@@ -542,6 +539,25 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | |||
542 | *ifap = ifp; | 539 | *ifap = ifp; |
543 | } | 540 | } |
544 | 541 | ||
542 | /* | ||
543 | * Hash function taken from net_alias.c | ||
544 | */ | ||
545 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
546 | { | ||
547 | __u32 word; | ||
548 | |||
549 | /* | ||
550 | * We perform the hash function over the last 64 bits of the address | ||
551 | * This will include the IEEE address token on links that support it. | ||
552 | */ | ||
553 | |||
554 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | ||
555 | word ^= (word >> 16); | ||
556 | word ^= (word >> 8); | ||
557 | |||
558 | return ((word ^ (word >> 4)) & 0x0f); | ||
559 | } | ||
560 | |||
545 | /* On success it returns ifp with increased reference count */ | 561 | /* On success it returns ifp with increased reference count */ |
546 | 562 | ||
547 | static struct inet6_ifaddr * | 563 | static struct inet6_ifaddr * |
@@ -562,7 +578,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
562 | write_lock(&addrconf_hash_lock); | 578 | write_lock(&addrconf_hash_lock); |
563 | 579 | ||
564 | /* Ignore adding duplicate addresses on an interface */ | 580 | /* Ignore adding duplicate addresses on an interface */ |
565 | if (ipv6_chk_same_addr(&init_net, addr, idev->dev)) { | 581 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
566 | ADBG(("ipv6_add_addr: already assigned\n")); | 582 | ADBG(("ipv6_add_addr: already assigned\n")); |
567 | err = -EEXIST; | 583 | err = -EEXIST; |
568 | goto out; | 584 | goto out; |
@@ -752,9 +768,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
752 | if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { | 768 | if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { |
753 | struct in6_addr prefix; | 769 | struct in6_addr prefix; |
754 | struct rt6_info *rt; | 770 | struct rt6_info *rt; |
755 | 771 | struct net *net = dev_net(ifp->idev->dev); | |
756 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); | 772 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); |
757 | rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1); | 773 | rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); |
758 | 774 | ||
759 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 775 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { |
760 | if (onlink == 0) { | 776 | if (onlink == 0) { |
@@ -894,20 +910,40 @@ out: | |||
894 | /* | 910 | /* |
895 | * Choose an appropriate source address (RFC3484) | 911 | * Choose an appropriate source address (RFC3484) |
896 | */ | 912 | */ |
913 | enum { | ||
914 | IPV6_SADDR_RULE_INIT = 0, | ||
915 | IPV6_SADDR_RULE_LOCAL, | ||
916 | IPV6_SADDR_RULE_SCOPE, | ||
917 | IPV6_SADDR_RULE_PREFERRED, | ||
918 | #ifdef CONFIG_IPV6_MIP6 | ||
919 | IPV6_SADDR_RULE_HOA, | ||
920 | #endif | ||
921 | IPV6_SADDR_RULE_OIF, | ||
922 | IPV6_SADDR_RULE_LABEL, | ||
923 | #ifdef CONFIG_IPV6_PRIVACY | ||
924 | IPV6_SADDR_RULE_PRIVACY, | ||
925 | #endif | ||
926 | IPV6_SADDR_RULE_ORCHID, | ||
927 | IPV6_SADDR_RULE_PREFIX, | ||
928 | IPV6_SADDR_RULE_MAX | ||
929 | }; | ||
930 | |||
897 | struct ipv6_saddr_score { | 931 | struct ipv6_saddr_score { |
898 | int addr_type; | 932 | int rule; |
899 | unsigned int attrs; | 933 | int addr_type; |
900 | int matchlen; | 934 | struct inet6_ifaddr *ifa; |
901 | int scope; | 935 | DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX); |
902 | unsigned int rule; | 936 | int scopedist; |
937 | int matchlen; | ||
903 | }; | 938 | }; |
904 | 939 | ||
905 | #define IPV6_SADDR_SCORE_LOCAL 0x0001 | 940 | struct ipv6_saddr_dst { |
906 | #define IPV6_SADDR_SCORE_PREFERRED 0x0004 | 941 | const struct in6_addr *addr; |
907 | #define IPV6_SADDR_SCORE_HOA 0x0008 | 942 | int ifindex; |
908 | #define IPV6_SADDR_SCORE_OIF 0x0010 | 943 | int scope; |
909 | #define IPV6_SADDR_SCORE_LABEL 0x0020 | 944 | int label; |
910 | #define IPV6_SADDR_SCORE_PRIVACY 0x0040 | 945 | unsigned int prefs; |
946 | }; | ||
911 | 947 | ||
912 | static inline int ipv6_saddr_preferred(int type) | 948 | static inline int ipv6_saddr_preferred(int type) |
913 | { | 949 | { |
@@ -917,27 +953,152 @@ static inline int ipv6_saddr_preferred(int type) | |||
917 | return 0; | 953 | return 0; |
918 | } | 954 | } |
919 | 955 | ||
920 | int ipv6_dev_get_saddr(struct net_device *daddr_dev, | 956 | static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, |
921 | struct in6_addr *daddr, struct in6_addr *saddr) | 957 | struct ipv6_saddr_dst *dst, |
958 | int i) | ||
922 | { | 959 | { |
923 | struct ipv6_saddr_score hiscore; | 960 | int ret; |
924 | struct inet6_ifaddr *ifa_result = NULL; | 961 | |
925 | int daddr_type = __ipv6_addr_type(daddr); | 962 | if (i <= score->rule) { |
926 | int daddr_scope = __ipv6_addr_src_scope(daddr_type); | 963 | switch (i) { |
927 | int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0; | 964 | case IPV6_SADDR_RULE_SCOPE: |
928 | u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex); | 965 | ret = score->scopedist; |
966 | break; | ||
967 | case IPV6_SADDR_RULE_PREFIX: | ||
968 | ret = score->matchlen; | ||
969 | break; | ||
970 | default: | ||
971 | ret = !!test_bit(i, score->scorebits); | ||
972 | } | ||
973 | goto out; | ||
974 | } | ||
975 | |||
976 | switch (i) { | ||
977 | case IPV6_SADDR_RULE_INIT: | ||
978 | /* Rule 0: remember if hiscore is not ready yet */ | ||
979 | ret = !!score->ifa; | ||
980 | break; | ||
981 | case IPV6_SADDR_RULE_LOCAL: | ||
982 | /* Rule 1: Prefer same address */ | ||
983 | ret = ipv6_addr_equal(&score->ifa->addr, dst->addr); | ||
984 | break; | ||
985 | case IPV6_SADDR_RULE_SCOPE: | ||
986 | /* Rule 2: Prefer appropriate scope | ||
987 | * | ||
988 | * ret | ||
989 | * ^ | ||
990 | * -1 | d 15 | ||
991 | * ---+--+-+---> scope | ||
992 | * | | ||
993 | * | d is scope of the destination. | ||
994 | * B-d | \ | ||
995 | * | \ <- smaller scope is better if | ||
996 | * B-15 | \ if scope is enough for destinaion. | ||
997 | * | ret = B - scope (-1 <= scope >= d <= 15). | ||
998 | * d-C-1 | / | ||
999 | * |/ <- greater is better | ||
1000 | * -C / if scope is not enough for destination. | ||
1001 | * /| ret = scope - C (-1 <= d < scope <= 15). | ||
1002 | * | ||
1003 | * d - C - 1 < B -15 (for all -1 <= d <= 15). | ||
1004 | * C > d + 14 - B >= 15 + 14 - B = 29 - B. | ||
1005 | * Assume B = 0 and we get C > 29. | ||
1006 | */ | ||
1007 | ret = __ipv6_addr_src_scope(score->addr_type); | ||
1008 | if (ret >= dst->scope) | ||
1009 | ret = -ret; | ||
1010 | else | ||
1011 | ret -= 128; /* 30 is enough */ | ||
1012 | score->scopedist = ret; | ||
1013 | break; | ||
1014 | case IPV6_SADDR_RULE_PREFERRED: | ||
1015 | /* Rule 3: Avoid deprecated and optimistic addresses */ | ||
1016 | ret = ipv6_saddr_preferred(score->addr_type) || | ||
1017 | !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)); | ||
1018 | break; | ||
1019 | #ifdef CONFIG_IPV6_MIP6 | ||
1020 | case IPV6_SADDR_RULE_HOA: | ||
1021 | { | ||
1022 | /* Rule 4: Prefer home address */ | ||
1023 | int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA); | ||
1024 | ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome; | ||
1025 | break; | ||
1026 | } | ||
1027 | #endif | ||
1028 | case IPV6_SADDR_RULE_OIF: | ||
1029 | /* Rule 5: Prefer outgoing interface */ | ||
1030 | ret = (!dst->ifindex || | ||
1031 | dst->ifindex == score->ifa->idev->dev->ifindex); | ||
1032 | break; | ||
1033 | case IPV6_SADDR_RULE_LABEL: | ||
1034 | /* Rule 6: Prefer matching label */ | ||
1035 | ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, | ||
1036 | score->ifa->idev->dev->ifindex) == dst->label; | ||
1037 | break; | ||
1038 | #ifdef CONFIG_IPV6_PRIVACY | ||
1039 | case IPV6_SADDR_RULE_PRIVACY: | ||
1040 | { | ||
1041 | /* Rule 7: Prefer public address | ||
1042 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
1043 | */ | ||
1044 | int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? | ||
1045 | !!(dst->prefs & IPV6_PREFER_SRC_TMP) : | ||
1046 | score->ifa->idev->cnf.use_tempaddr >= 2; | ||
1047 | ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp; | ||
1048 | break; | ||
1049 | } | ||
1050 | #endif | ||
1051 | case IPV6_SADDR_RULE_ORCHID: | ||
1052 | /* Rule 8-: Prefer ORCHID vs ORCHID or | ||
1053 | * non-ORCHID vs non-ORCHID | ||
1054 | */ | ||
1055 | ret = !(ipv6_addr_orchid(&score->ifa->addr) ^ | ||
1056 | ipv6_addr_orchid(dst->addr)); | ||
1057 | break; | ||
1058 | case IPV6_SADDR_RULE_PREFIX: | ||
1059 | /* Rule 8: Use longest matching prefix */ | ||
1060 | score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr, | ||
1061 | dst->addr); | ||
1062 | break; | ||
1063 | default: | ||
1064 | ret = 0; | ||
1065 | } | ||
1066 | |||
1067 | if (ret) | ||
1068 | __set_bit(i, score->scorebits); | ||
1069 | score->rule = i; | ||
1070 | out: | ||
1071 | return ret; | ||
1072 | } | ||
1073 | |||
1074 | int ipv6_dev_get_saddr(struct net_device *dst_dev, | ||
1075 | const struct in6_addr *daddr, unsigned int prefs, | ||
1076 | struct in6_addr *saddr) | ||
1077 | { | ||
1078 | struct ipv6_saddr_score scores[2], | ||
1079 | *score = &scores[0], *hiscore = &scores[1]; | ||
1080 | struct net *net = dev_net(dst_dev); | ||
1081 | struct ipv6_saddr_dst dst; | ||
929 | struct net_device *dev; | 1082 | struct net_device *dev; |
1083 | int dst_type; | ||
1084 | |||
1085 | dst_type = __ipv6_addr_type(daddr); | ||
1086 | dst.addr = daddr; | ||
1087 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; | ||
1088 | dst.scope = __ipv6_addr_src_scope(dst_type); | ||
1089 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); | ||
1090 | dst.prefs = prefs; | ||
930 | 1091 | ||
931 | memset(&hiscore, 0, sizeof(hiscore)); | 1092 | hiscore->rule = -1; |
1093 | hiscore->ifa = NULL; | ||
932 | 1094 | ||
933 | read_lock(&dev_base_lock); | 1095 | read_lock(&dev_base_lock); |
934 | rcu_read_lock(); | 1096 | rcu_read_lock(); |
935 | 1097 | ||
936 | for_each_netdev(&init_net, dev) { | 1098 | for_each_netdev(net, dev) { |
937 | struct inet6_dev *idev; | 1099 | struct inet6_dev *idev; |
938 | struct inet6_ifaddr *ifa; | ||
939 | 1100 | ||
940 | /* Rule 0: Candidate Source Address (section 4) | 1101 | /* Candidate Source Address (section 4) |
941 | * - multicast and link-local destination address, | 1102 | * - multicast and link-local destination address, |
942 | * the set of candidate source address MUST only | 1103 | * the set of candidate source address MUST only |
943 | * include addresses assigned to interfaces | 1104 | * include addresses assigned to interfaces |
@@ -949,9 +1110,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
949 | * belonging to the same site as the outgoing | 1110 | * belonging to the same site as the outgoing |
950 | * interface.) | 1111 | * interface.) |
951 | */ | 1112 | */ |
952 | if ((daddr_type & IPV6_ADDR_MULTICAST || | 1113 | if (((dst_type & IPV6_ADDR_MULTICAST) || |
953 | daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && | 1114 | dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && |
954 | daddr_dev && dev != daddr_dev) | 1115 | dst.ifindex && dev->ifindex != dst.ifindex) |
955 | continue; | 1116 | continue; |
956 | 1117 | ||
957 | idev = __in6_dev_get(dev); | 1118 | idev = __in6_dev_get(dev); |
@@ -959,12 +1120,10 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
959 | continue; | 1120 | continue; |
960 | 1121 | ||
961 | read_lock_bh(&idev->lock); | 1122 | read_lock_bh(&idev->lock); |
962 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1123 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { |
963 | struct ipv6_saddr_score score; | 1124 | int i; |
964 | |||
965 | score.addr_type = __ipv6_addr_type(&ifa->addr); | ||
966 | 1125 | ||
967 | /* Rule 0: | 1126 | /* |
968 | * - Tentative Address (RFC2462 section 5.4) | 1127 | * - Tentative Address (RFC2462 section 5.4) |
969 | * - A tentative address is not considered | 1128 | * - A tentative address is not considered |
970 | * "assigned to an interface" in the traditional | 1129 | * "assigned to an interface" in the traditional |
@@ -974,11 +1133,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
974 | * addresses, and the unspecified address MUST | 1133 | * addresses, and the unspecified address MUST |
975 | * NOT be included in a candidate set. | 1134 | * NOT be included in a candidate set. |
976 | */ | 1135 | */ |
977 | if ((ifa->flags & IFA_F_TENTATIVE) && | 1136 | if ((score->ifa->flags & IFA_F_TENTATIVE) && |
978 | (!(ifa->flags & IFA_F_OPTIMISTIC))) | 1137 | (!(score->ifa->flags & IFA_F_OPTIMISTIC))) |
979 | continue; | 1138 | continue; |
980 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 1139 | |
981 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 1140 | score->addr_type = __ipv6_addr_type(&score->ifa->addr); |
1141 | |||
1142 | if (unlikely(score->addr_type == IPV6_ADDR_ANY || | ||
1143 | score->addr_type & IPV6_ADDR_MULTICAST)) { | ||
982 | LIMIT_NETDEBUG(KERN_DEBUG | 1144 | LIMIT_NETDEBUG(KERN_DEBUG |
983 | "ADDRCONF: unspecified / multicast address " | 1145 | "ADDRCONF: unspecified / multicast address " |
984 | "assigned as unicast address on %s", | 1146 | "assigned as unicast address on %s", |
@@ -986,207 +1148,63 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
986 | continue; | 1148 | continue; |
987 | } | 1149 | } |
988 | 1150 | ||
989 | score.attrs = 0; | 1151 | score->rule = -1; |
990 | score.matchlen = 0; | 1152 | bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); |
991 | score.scope = 0; | 1153 | |
992 | score.rule = 0; | 1154 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { |
1155 | int minihiscore, miniscore; | ||
1156 | |||
1157 | minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); | ||
1158 | miniscore = ipv6_get_saddr_eval(score, &dst, i); | ||
1159 | |||
1160 | if (minihiscore > miniscore) { | ||
1161 | if (i == IPV6_SADDR_RULE_SCOPE && | ||
1162 | score->scopedist > 0) { | ||
1163 | /* | ||
1164 | * special case: | ||
1165 | * each remaining entry | ||
1166 | * has too small (not enough) | ||
1167 | * scope, because ifa entries | ||
1168 | * are sorted by their scope | ||
1169 | * values. | ||
1170 | */ | ||
1171 | goto try_nextdev; | ||
1172 | } | ||
1173 | break; | ||
1174 | } else if (minihiscore < miniscore) { | ||
1175 | struct ipv6_saddr_score *tmp; | ||
993 | 1176 | ||
994 | if (ifa_result == NULL) { | 1177 | if (hiscore->ifa) |
995 | /* record it if the first available entry */ | 1178 | in6_ifa_put(hiscore->ifa); |
996 | goto record_it; | ||
997 | } | ||
998 | 1179 | ||
999 | /* Rule 1: Prefer same address */ | 1180 | in6_ifa_hold(score->ifa); |
1000 | if (hiscore.rule < 1) { | ||
1001 | if (ipv6_addr_equal(&ifa_result->addr, daddr)) | ||
1002 | hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL; | ||
1003 | hiscore.rule++; | ||
1004 | } | ||
1005 | if (ipv6_addr_equal(&ifa->addr, daddr)) { | ||
1006 | score.attrs |= IPV6_SADDR_SCORE_LOCAL; | ||
1007 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) { | ||
1008 | score.rule = 1; | ||
1009 | goto record_it; | ||
1010 | } | ||
1011 | } else { | ||
1012 | if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL) | ||
1013 | continue; | ||
1014 | } | ||
1015 | 1181 | ||
1016 | /* Rule 2: Prefer appropriate scope */ | 1182 | tmp = hiscore; |
1017 | if (hiscore.rule < 2) { | 1183 | hiscore = score; |
1018 | hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type); | 1184 | score = tmp; |
1019 | hiscore.rule++; | ||
1020 | } | ||
1021 | score.scope = __ipv6_addr_src_scope(score.addr_type); | ||
1022 | if (hiscore.scope < score.scope) { | ||
1023 | if (hiscore.scope < daddr_scope) { | ||
1024 | score.rule = 2; | ||
1025 | goto record_it; | ||
1026 | } else | ||
1027 | continue; | ||
1028 | } else if (score.scope < hiscore.scope) { | ||
1029 | if (score.scope < daddr_scope) | ||
1030 | break; /* addresses sorted by scope */ | ||
1031 | else { | ||
1032 | score.rule = 2; | ||
1033 | goto record_it; | ||
1034 | } | ||
1035 | } | ||
1036 | 1185 | ||
1037 | /* Rule 3: Avoid deprecated and optimistic addresses */ | 1186 | /* restore our iterator */ |
1038 | if (hiscore.rule < 3) { | 1187 | score->ifa = hiscore->ifa; |
1039 | if (ipv6_saddr_preferred(hiscore.addr_type) || | ||
1040 | (((ifa_result->flags & | ||
1041 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) | ||
1042 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
1043 | hiscore.rule++; | ||
1044 | } | ||
1045 | if (ipv6_saddr_preferred(score.addr_type) || | ||
1046 | (((ifa->flags & | ||
1047 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { | ||
1048 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; | ||
1049 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { | ||
1050 | score.rule = 3; | ||
1051 | goto record_it; | ||
1052 | } | ||
1053 | } else { | ||
1054 | if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED) | ||
1055 | continue; | ||
1056 | } | ||
1057 | 1188 | ||
1058 | /* Rule 4: Prefer home address */ | 1189 | break; |
1059 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
1060 | if (hiscore.rule < 4) { | ||
1061 | if (ifa_result->flags & IFA_F_HOMEADDRESS) | ||
1062 | hiscore.attrs |= IPV6_SADDR_SCORE_HOA; | ||
1063 | hiscore.rule++; | ||
1064 | } | ||
1065 | if (ifa->flags & IFA_F_HOMEADDRESS) { | ||
1066 | score.attrs |= IPV6_SADDR_SCORE_HOA; | ||
1067 | if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) { | ||
1068 | score.rule = 4; | ||
1069 | goto record_it; | ||
1070 | } | ||
1071 | } else { | ||
1072 | if (hiscore.attrs & IPV6_SADDR_SCORE_HOA) | ||
1073 | continue; | ||
1074 | } | ||
1075 | #else | ||
1076 | if (hiscore.rule < 4) | ||
1077 | hiscore.rule++; | ||
1078 | #endif | ||
1079 | |||
1080 | /* Rule 5: Prefer outgoing interface */ | ||
1081 | if (hiscore.rule < 5) { | ||
1082 | if (daddr_dev == NULL || | ||
1083 | daddr_dev == ifa_result->idev->dev) | ||
1084 | hiscore.attrs |= IPV6_SADDR_SCORE_OIF; | ||
1085 | hiscore.rule++; | ||
1086 | } | ||
1087 | if (daddr_dev == NULL || | ||
1088 | daddr_dev == ifa->idev->dev) { | ||
1089 | score.attrs |= IPV6_SADDR_SCORE_OIF; | ||
1090 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) { | ||
1091 | score.rule = 5; | ||
1092 | goto record_it; | ||
1093 | } | ||
1094 | } else { | ||
1095 | if (hiscore.attrs & IPV6_SADDR_SCORE_OIF) | ||
1096 | continue; | ||
1097 | } | ||
1098 | |||
1099 | /* Rule 6: Prefer matching label */ | ||
1100 | if (hiscore.rule < 6) { | ||
1101 | if (ipv6_addr_label(&ifa_result->addr, | ||
1102 | hiscore.addr_type, | ||
1103 | ifa_result->idev->dev->ifindex) == daddr_label) | ||
1104 | hiscore.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
1105 | hiscore.rule++; | ||
1106 | } | ||
1107 | if (ipv6_addr_label(&ifa->addr, | ||
1108 | score.addr_type, | ||
1109 | ifa->idev->dev->ifindex) == daddr_label) { | ||
1110 | score.attrs |= IPV6_SADDR_SCORE_LABEL; | ||
1111 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) { | ||
1112 | score.rule = 6; | ||
1113 | goto record_it; | ||
1114 | } | ||
1115 | } else { | ||
1116 | if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL) | ||
1117 | continue; | ||
1118 | } | ||
1119 | |||
1120 | #ifdef CONFIG_IPV6_PRIVACY | ||
1121 | /* Rule 7: Prefer public address | ||
1122 | * Note: prefer temprary address if use_tempaddr >= 2 | ||
1123 | */ | ||
1124 | if (hiscore.rule < 7) { | ||
1125 | if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^ | ||
1126 | (ifa_result->idev->cnf.use_tempaddr >= 2)) | ||
1127 | hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
1128 | hiscore.rule++; | ||
1129 | } | ||
1130 | if ((!(ifa->flags & IFA_F_TEMPORARY)) ^ | ||
1131 | (ifa->idev->cnf.use_tempaddr >= 2)) { | ||
1132 | score.attrs |= IPV6_SADDR_SCORE_PRIVACY; | ||
1133 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) { | ||
1134 | score.rule = 7; | ||
1135 | goto record_it; | ||
1136 | } | 1190 | } |
1137 | } else { | ||
1138 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) | ||
1139 | continue; | ||
1140 | } | 1191 | } |
1141 | #else | ||
1142 | if (hiscore.rule < 7) | ||
1143 | hiscore.rule++; | ||
1144 | #endif | ||
1145 | /* Rule 8: Use longest matching prefix */ | ||
1146 | if (hiscore.rule < 8) { | ||
1147 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | ||
1148 | hiscore.rule++; | ||
1149 | } | ||
1150 | score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); | ||
1151 | if (score.matchlen > hiscore.matchlen) { | ||
1152 | score.rule = 8; | ||
1153 | goto record_it; | ||
1154 | } | ||
1155 | #if 0 | ||
1156 | else if (score.matchlen < hiscore.matchlen) | ||
1157 | continue; | ||
1158 | #endif | ||
1159 | |||
1160 | /* Final Rule: choose first available one */ | ||
1161 | continue; | ||
1162 | record_it: | ||
1163 | if (ifa_result) | ||
1164 | in6_ifa_put(ifa_result); | ||
1165 | in6_ifa_hold(ifa); | ||
1166 | ifa_result = ifa; | ||
1167 | hiscore = score; | ||
1168 | } | 1192 | } |
1193 | try_nextdev: | ||
1169 | read_unlock_bh(&idev->lock); | 1194 | read_unlock_bh(&idev->lock); |
1170 | } | 1195 | } |
1171 | rcu_read_unlock(); | 1196 | rcu_read_unlock(); |
1172 | read_unlock(&dev_base_lock); | 1197 | read_unlock(&dev_base_lock); |
1173 | 1198 | ||
1174 | if (!ifa_result) | 1199 | if (!hiscore->ifa) |
1175 | return -EADDRNOTAVAIL; | 1200 | return -EADDRNOTAVAIL; |
1176 | 1201 | ||
1177 | ipv6_addr_copy(saddr, &ifa_result->addr); | 1202 | ipv6_addr_copy(saddr, &hiscore->ifa->addr); |
1178 | in6_ifa_put(ifa_result); | 1203 | in6_ifa_put(hiscore->ifa); |
1179 | return 0; | 1204 | return 0; |
1180 | } | 1205 | } |
1181 | 1206 | ||
1182 | 1207 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | |
1183 | int ipv6_get_saddr(struct dst_entry *dst, | ||
1184 | struct in6_addr *daddr, struct in6_addr *saddr) | ||
1185 | { | ||
1186 | return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr); | ||
1187 | } | ||
1188 | |||
1189 | EXPORT_SYMBOL(ipv6_get_saddr); | ||
1190 | 1208 | ||
1191 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1209 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
1192 | unsigned char banned_flags) | 1210 | unsigned char banned_flags) |
@@ -1232,7 +1250,7 @@ int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | |||
1232 | 1250 | ||
1233 | read_lock_bh(&addrconf_hash_lock); | 1251 | read_lock_bh(&addrconf_hash_lock); |
1234 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1252 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { |
1235 | if (ifp->idev->dev->nd_net != net) | 1253 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1236 | continue; | 1254 | continue; |
1237 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1255 | if (ipv6_addr_equal(&ifp->addr, addr) && |
1238 | !(ifp->flags&IFA_F_TENTATIVE)) { | 1256 | !(ifp->flags&IFA_F_TENTATIVE)) { |
@@ -1254,7 +1272,7 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1254 | u8 hash = ipv6_addr_hash(addr); | 1272 | u8 hash = ipv6_addr_hash(addr); |
1255 | 1273 | ||
1256 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1274 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { |
1257 | if (ifp->idev->dev->nd_net != net) | 1275 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1258 | continue; | 1276 | continue; |
1259 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1277 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1260 | if (dev == NULL || ifp->idev->dev == dev) | 1278 | if (dev == NULL || ifp->idev->dev == dev) |
@@ -1264,7 +1282,32 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1264 | return ifp != NULL; | 1282 | return ifp != NULL; |
1265 | } | 1283 | } |
1266 | 1284 | ||
1267 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr, | 1285 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) |
1286 | { | ||
1287 | struct inet6_dev *idev; | ||
1288 | struct inet6_ifaddr *ifa; | ||
1289 | int onlink; | ||
1290 | |||
1291 | onlink = 0; | ||
1292 | rcu_read_lock(); | ||
1293 | idev = __in6_dev_get(dev); | ||
1294 | if (idev) { | ||
1295 | read_lock_bh(&idev->lock); | ||
1296 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | ||
1297 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | ||
1298 | ifa->prefix_len); | ||
1299 | if (onlink) | ||
1300 | break; | ||
1301 | } | ||
1302 | read_unlock_bh(&idev->lock); | ||
1303 | } | ||
1304 | rcu_read_unlock(); | ||
1305 | return onlink; | ||
1306 | } | ||
1307 | |||
1308 | EXPORT_SYMBOL(ipv6_chk_prefix); | ||
1309 | |||
1310 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, | ||
1268 | struct net_device *dev, int strict) | 1311 | struct net_device *dev, int strict) |
1269 | { | 1312 | { |
1270 | struct inet6_ifaddr * ifp; | 1313 | struct inet6_ifaddr * ifp; |
@@ -1272,7 +1315,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr, | |||
1272 | 1315 | ||
1273 | read_lock_bh(&addrconf_hash_lock); | 1316 | read_lock_bh(&addrconf_hash_lock); |
1274 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1317 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { |
1275 | if (ifp->idev->dev->nd_net != net) | 1318 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1276 | continue; | 1319 | continue; |
1277 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1320 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1278 | if (dev == NULL || ifp->idev->dev == dev || | 1321 | if (dev == NULL || ifp->idev->dev == dev || |
@@ -1449,6 +1492,29 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev) | |||
1449 | return 0; | 1492 | return 0; |
1450 | } | 1493 | } |
1451 | 1494 | ||
1495 | int __ipv6_isatap_ifid(u8 *eui, __be32 addr) | ||
1496 | { | ||
1497 | eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || | ||
1498 | ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || | ||
1499 | ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || | ||
1500 | ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) || | ||
1501 | ipv4_is_test_198(addr) || ipv4_is_multicast(addr) || | ||
1502 | ipv4_is_lbcast(addr)) ? 0x00 : 0x02; | ||
1503 | eui[1] = 0; | ||
1504 | eui[2] = 0x5E; | ||
1505 | eui[3] = 0xFE; | ||
1506 | memcpy(eui + 4, &addr, 4); | ||
1507 | return 0; | ||
1508 | } | ||
1509 | EXPORT_SYMBOL(__ipv6_isatap_ifid); | ||
1510 | |||
1511 | static int addrconf_ifid_sit(u8 *eui, struct net_device *dev) | ||
1512 | { | ||
1513 | if (dev->priv_flags & IFF_ISATAP) | ||
1514 | return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr); | ||
1515 | return -1; | ||
1516 | } | ||
1517 | |||
1452 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | 1518 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) |
1453 | { | 1519 | { |
1454 | switch (dev->type) { | 1520 | switch (dev->type) { |
@@ -1461,8 +1527,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
1461 | case ARPHRD_INFINIBAND: | 1527 | case ARPHRD_INFINIBAND: |
1462 | return addrconf_ifid_infiniband(eui, dev); | 1528 | return addrconf_ifid_infiniband(eui, dev); |
1463 | case ARPHRD_SIT: | 1529 | case ARPHRD_SIT: |
1464 | if (dev->priv_flags & IFF_ISATAP) | 1530 | return addrconf_ifid_sit(eui, dev); |
1465 | return ipv6_isatap_eui64(eui, *(__be32 *)dev->dev_addr); | ||
1466 | } | 1531 | } |
1467 | return -1; | 1532 | return -1; |
1468 | } | 1533 | } |
@@ -1574,7 +1639,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
1574 | .fc_expires = expires, | 1639 | .fc_expires = expires, |
1575 | .fc_dst_len = plen, | 1640 | .fc_dst_len = plen, |
1576 | .fc_flags = RTF_UP | flags, | 1641 | .fc_flags = RTF_UP | flags, |
1577 | .fc_nlinfo.nl_net = &init_net, | 1642 | .fc_nlinfo.nl_net = dev_net(dev), |
1578 | }; | 1643 | }; |
1579 | 1644 | ||
1580 | ipv6_addr_copy(&cfg.fc_dst, pfx); | 1645 | ipv6_addr_copy(&cfg.fc_dst, pfx); |
@@ -1601,7 +1666,7 @@ static void addrconf_add_mroute(struct net_device *dev) | |||
1601 | .fc_ifindex = dev->ifindex, | 1666 | .fc_ifindex = dev->ifindex, |
1602 | .fc_dst_len = 8, | 1667 | .fc_dst_len = 8, |
1603 | .fc_flags = RTF_UP, | 1668 | .fc_flags = RTF_UP, |
1604 | .fc_nlinfo.nl_net = &init_net, | 1669 | .fc_nlinfo.nl_net = dev_net(dev), |
1605 | }; | 1670 | }; |
1606 | 1671 | ||
1607 | ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); | 1672 | ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); |
@@ -1618,7 +1683,7 @@ static void sit_route_add(struct net_device *dev) | |||
1618 | .fc_ifindex = dev->ifindex, | 1683 | .fc_ifindex = dev->ifindex, |
1619 | .fc_dst_len = 96, | 1684 | .fc_dst_len = 96, |
1620 | .fc_flags = RTF_UP | RTF_NONEXTHOP, | 1685 | .fc_flags = RTF_UP | RTF_NONEXTHOP, |
1621 | .fc_nlinfo.nl_net = &init_net, | 1686 | .fc_nlinfo.nl_net = dev_net(dev), |
1622 | }; | 1687 | }; |
1623 | 1688 | ||
1624 | /* prefix length - 96 bits "::d.d.d.d" */ | 1689 | /* prefix length - 96 bits "::d.d.d.d" */ |
@@ -1719,7 +1784,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1719 | 1784 | ||
1720 | if (pinfo->onlink) { | 1785 | if (pinfo->onlink) { |
1721 | struct rt6_info *rt; | 1786 | struct rt6_info *rt; |
1722 | rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1); | 1787 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, |
1788 | dev->ifindex, 1); | ||
1723 | 1789 | ||
1724 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 1790 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { |
1725 | if (rt->rt6i_flags&RTF_EXPIRES) { | 1791 | if (rt->rt6i_flags&RTF_EXPIRES) { |
@@ -1762,7 +1828,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1762 | 1828 | ||
1763 | ok: | 1829 | ok: |
1764 | 1830 | ||
1765 | ifp = ipv6_get_ifaddr(&init_net, &addr, dev, 1); | 1831 | ifp = ipv6_get_ifaddr(dev_net(dev), &addr, dev, 1); |
1766 | 1832 | ||
1767 | if (ifp == NULL && valid_lft) { | 1833 | if (ifp == NULL && valid_lft) { |
1768 | int max_addresses = in6_dev->cnf.max_addresses; | 1834 | int max_addresses = in6_dev->cnf.max_addresses; |
@@ -1888,7 +1954,7 @@ ok: | |||
1888 | * Special case for SIT interfaces where we create a new "virtual" | 1954 | * Special case for SIT interfaces where we create a new "virtual" |
1889 | * device. | 1955 | * device. |
1890 | */ | 1956 | */ |
1891 | int addrconf_set_dstaddr(void __user *arg) | 1957 | int addrconf_set_dstaddr(struct net *net, void __user *arg) |
1892 | { | 1958 | { |
1893 | struct in6_ifreq ireq; | 1959 | struct in6_ifreq ireq; |
1894 | struct net_device *dev; | 1960 | struct net_device *dev; |
@@ -1900,7 +1966,7 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1900 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) | 1966 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) |
1901 | goto err_exit; | 1967 | goto err_exit; |
1902 | 1968 | ||
1903 | dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex); | 1969 | dev = __dev_get_by_index(net, ireq.ifr6_ifindex); |
1904 | 1970 | ||
1905 | err = -ENODEV; | 1971 | err = -ENODEV; |
1906 | if (dev == NULL) | 1972 | if (dev == NULL) |
@@ -1931,7 +1997,8 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1931 | 1997 | ||
1932 | if (err == 0) { | 1998 | if (err == 0) { |
1933 | err = -ENOBUFS; | 1999 | err = -ENOBUFS; |
1934 | if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL) | 2000 | dev = __dev_get_by_name(net, p.name); |
2001 | if (!dev) | ||
1935 | goto err_exit; | 2002 | goto err_exit; |
1936 | err = dev_open(dev); | 2003 | err = dev_open(dev); |
1937 | } | 2004 | } |
@@ -1946,8 +2013,9 @@ err_exit: | |||
1946 | /* | 2013 | /* |
1947 | * Manual configuration of address on an interface | 2014 | * Manual configuration of address on an interface |
1948 | */ | 2015 | */ |
1949 | static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | 2016 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, |
1950 | __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft) | 2017 | int plen, __u8 ifa_flags, __u32 prefered_lft, |
2018 | __u32 valid_lft) | ||
1951 | { | 2019 | { |
1952 | struct inet6_ifaddr *ifp; | 2020 | struct inet6_ifaddr *ifp; |
1953 | struct inet6_dev *idev; | 2021 | struct inet6_dev *idev; |
@@ -1961,7 +2029,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1961 | if (!valid_lft || prefered_lft > valid_lft) | 2029 | if (!valid_lft || prefered_lft > valid_lft) |
1962 | return -EINVAL; | 2030 | return -EINVAL; |
1963 | 2031 | ||
1964 | if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL) | 2032 | dev = __dev_get_by_index(net, ifindex); |
2033 | if (!dev) | ||
1965 | return -ENODEV; | 2034 | return -ENODEV; |
1966 | 2035 | ||
1967 | if ((idev = addrconf_add_dev(dev)) == NULL) | 2036 | if ((idev = addrconf_add_dev(dev)) == NULL) |
@@ -2006,13 +2075,15 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
2006 | return PTR_ERR(ifp); | 2075 | return PTR_ERR(ifp); |
2007 | } | 2076 | } |
2008 | 2077 | ||
2009 | static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) | 2078 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, |
2079 | int plen) | ||
2010 | { | 2080 | { |
2011 | struct inet6_ifaddr *ifp; | 2081 | struct inet6_ifaddr *ifp; |
2012 | struct inet6_dev *idev; | 2082 | struct inet6_dev *idev; |
2013 | struct net_device *dev; | 2083 | struct net_device *dev; |
2014 | 2084 | ||
2015 | if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL) | 2085 | dev = __dev_get_by_index(net, ifindex); |
2086 | if (!dev) | ||
2016 | return -ENODEV; | 2087 | return -ENODEV; |
2017 | 2088 | ||
2018 | if ((idev = __in6_dev_get(dev)) == NULL) | 2089 | if ((idev = __in6_dev_get(dev)) == NULL) |
@@ -2040,7 +2111,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen) | |||
2040 | } | 2111 | } |
2041 | 2112 | ||
2042 | 2113 | ||
2043 | int addrconf_add_ifaddr(void __user *arg) | 2114 | int addrconf_add_ifaddr(struct net *net, void __user *arg) |
2044 | { | 2115 | { |
2045 | struct in6_ifreq ireq; | 2116 | struct in6_ifreq ireq; |
2046 | int err; | 2117 | int err; |
@@ -2052,13 +2123,14 @@ int addrconf_add_ifaddr(void __user *arg) | |||
2052 | return -EFAULT; | 2123 | return -EFAULT; |
2053 | 2124 | ||
2054 | rtnl_lock(); | 2125 | rtnl_lock(); |
2055 | err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, | 2126 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, |
2056 | IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 2127 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, |
2128 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | ||
2057 | rtnl_unlock(); | 2129 | rtnl_unlock(); |
2058 | return err; | 2130 | return err; |
2059 | } | 2131 | } |
2060 | 2132 | ||
2061 | int addrconf_del_ifaddr(void __user *arg) | 2133 | int addrconf_del_ifaddr(struct net *net, void __user *arg) |
2062 | { | 2134 | { |
2063 | struct in6_ifreq ireq; | 2135 | struct in6_ifreq ireq; |
2064 | int err; | 2136 | int err; |
@@ -2070,7 +2142,8 @@ int addrconf_del_ifaddr(void __user *arg) | |||
2070 | return -EFAULT; | 2142 | return -EFAULT; |
2071 | 2143 | ||
2072 | rtnl_lock(); | 2144 | rtnl_lock(); |
2073 | err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); | 2145 | err = inet6_addr_del(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, |
2146 | ireq.ifr6_prefixlen); | ||
2074 | rtnl_unlock(); | 2147 | rtnl_unlock(); |
2075 | return err; | 2148 | return err; |
2076 | } | 2149 | } |
@@ -2081,6 +2154,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2081 | struct inet6_ifaddr * ifp; | 2154 | struct inet6_ifaddr * ifp; |
2082 | struct in6_addr addr; | 2155 | struct in6_addr addr; |
2083 | struct net_device *dev; | 2156 | struct net_device *dev; |
2157 | struct net *net = dev_net(idev->dev); | ||
2084 | int scope; | 2158 | int scope; |
2085 | 2159 | ||
2086 | ASSERT_RTNL(); | 2160 | ASSERT_RTNL(); |
@@ -2107,7 +2181,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2107 | return; | 2181 | return; |
2108 | } | 2182 | } |
2109 | 2183 | ||
2110 | for_each_netdev(&init_net, dev) { | 2184 | for_each_netdev(net, dev) { |
2111 | struct in_device * in_dev = __in_dev_get_rtnl(dev); | 2185 | struct in_device * in_dev = __in_dev_get_rtnl(dev); |
2112 | if (in_dev && (dev->flags & IFF_UP)) { | 2186 | if (in_dev && (dev->flags & IFF_UP)) { |
2113 | struct in_ifaddr * ifa; | 2187 | struct in_ifaddr * ifa; |
@@ -2270,15 +2344,16 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | |||
2270 | static void ip6_tnl_add_linklocal(struct inet6_dev *idev) | 2344 | static void ip6_tnl_add_linklocal(struct inet6_dev *idev) |
2271 | { | 2345 | { |
2272 | struct net_device *link_dev; | 2346 | struct net_device *link_dev; |
2347 | struct net *net = dev_net(idev->dev); | ||
2273 | 2348 | ||
2274 | /* first try to inherit the link-local address from the link device */ | 2349 | /* first try to inherit the link-local address from the link device */ |
2275 | if (idev->dev->iflink && | 2350 | if (idev->dev->iflink && |
2276 | (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) { | 2351 | (link_dev = __dev_get_by_index(net, idev->dev->iflink))) { |
2277 | if (!ipv6_inherit_linklocal(idev, link_dev)) | 2352 | if (!ipv6_inherit_linklocal(idev, link_dev)) |
2278 | return; | 2353 | return; |
2279 | } | 2354 | } |
2280 | /* then try to inherit it from any device */ | 2355 | /* then try to inherit it from any device */ |
2281 | for_each_netdev(&init_net, link_dev) { | 2356 | for_each_netdev(net, link_dev) { |
2282 | if (!ipv6_inherit_linklocal(idev, link_dev)) | 2357 | if (!ipv6_inherit_linklocal(idev, link_dev)) |
2283 | return; | 2358 | return; |
2284 | } | 2359 | } |
@@ -2311,9 +2386,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2311 | int run_pending = 0; | 2386 | int run_pending = 0; |
2312 | int err; | 2387 | int err; |
2313 | 2388 | ||
2314 | if (dev->nd_net != &init_net) | ||
2315 | return NOTIFY_DONE; | ||
2316 | |||
2317 | switch(event) { | 2389 | switch(event) { |
2318 | case NETDEV_REGISTER: | 2390 | case NETDEV_REGISTER: |
2319 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2391 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
@@ -2453,6 +2525,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2453 | { | 2525 | { |
2454 | struct inet6_dev *idev; | 2526 | struct inet6_dev *idev; |
2455 | struct inet6_ifaddr *ifa, **bifa; | 2527 | struct inet6_ifaddr *ifa, **bifa; |
2528 | struct net *net = dev_net(dev); | ||
2456 | int i; | 2529 | int i; |
2457 | 2530 | ||
2458 | ASSERT_RTNL(); | 2531 | ASSERT_RTNL(); |
@@ -2460,7 +2533,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2460 | if ((dev->flags & IFF_LOOPBACK) && how == 1) | 2533 | if ((dev->flags & IFF_LOOPBACK) && how == 1) |
2461 | how = 0; | 2534 | how = 0; |
2462 | 2535 | ||
2463 | rt6_ifdown(dev); | 2536 | rt6_ifdown(net, dev); |
2464 | neigh_ifdown(&nd_tbl, dev); | 2537 | neigh_ifdown(&nd_tbl, dev); |
2465 | 2538 | ||
2466 | idev = __in6_dev_get(dev); | 2539 | idev = __in6_dev_get(dev); |
@@ -2579,8 +2652,6 @@ static void addrconf_rs_timer(unsigned long data) | |||
2579 | 2652 | ||
2580 | spin_lock(&ifp->lock); | 2653 | spin_lock(&ifp->lock); |
2581 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { | 2654 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { |
2582 | struct in6_addr all_routers; | ||
2583 | |||
2584 | /* The wait after the last probe can be shorter */ | 2655 | /* The wait after the last probe can be shorter */ |
2585 | addrconf_mod_timer(ifp, AC_RS, | 2656 | addrconf_mod_timer(ifp, AC_RS, |
2586 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? | 2657 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? |
@@ -2588,9 +2659,7 @@ static void addrconf_rs_timer(unsigned long data) | |||
2588 | ifp->idev->cnf.rtr_solicit_interval); | 2659 | ifp->idev->cnf.rtr_solicit_interval); |
2589 | spin_unlock(&ifp->lock); | 2660 | spin_unlock(&ifp->lock); |
2590 | 2661 | ||
2591 | ipv6_addr_all_routers(&all_routers); | 2662 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
2592 | |||
2593 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); | ||
2594 | } else { | 2663 | } else { |
2595 | spin_unlock(&ifp->lock); | 2664 | spin_unlock(&ifp->lock); |
2596 | /* | 2665 | /* |
@@ -2677,7 +2746,6 @@ static void addrconf_dad_timer(unsigned long data) | |||
2677 | { | 2746 | { |
2678 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 2747 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; |
2679 | struct inet6_dev *idev = ifp->idev; | 2748 | struct inet6_dev *idev = ifp->idev; |
2680 | struct in6_addr unspec; | ||
2681 | struct in6_addr mcaddr; | 2749 | struct in6_addr mcaddr; |
2682 | 2750 | ||
2683 | read_lock_bh(&idev->lock); | 2751 | read_lock_bh(&idev->lock); |
@@ -2706,9 +2774,8 @@ static void addrconf_dad_timer(unsigned long data) | |||
2706 | read_unlock_bh(&idev->lock); | 2774 | read_unlock_bh(&idev->lock); |
2707 | 2775 | ||
2708 | /* send a neighbour solicitation for our addr */ | 2776 | /* send a neighbour solicitation for our addr */ |
2709 | memset(&unspec, 0, sizeof(unspec)); | ||
2710 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 2777 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
2711 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec); | 2778 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); |
2712 | out: | 2779 | out: |
2713 | in6_ifa_put(ifp); | 2780 | in6_ifa_put(ifp); |
2714 | } | 2781 | } |
@@ -2731,16 +2798,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
2731 | ifp->idev->cnf.rtr_solicits > 0 && | 2798 | ifp->idev->cnf.rtr_solicits > 0 && |
2732 | (dev->flags&IFF_LOOPBACK) == 0 && | 2799 | (dev->flags&IFF_LOOPBACK) == 0 && |
2733 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { | 2800 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { |
2734 | struct in6_addr all_routers; | ||
2735 | |||
2736 | ipv6_addr_all_routers(&all_routers); | ||
2737 | |||
2738 | /* | 2801 | /* |
2739 | * If a host as already performed a random delay | 2802 | * If a host as already performed a random delay |
2740 | * [...] as part of DAD [...] there is no need | 2803 | * [...] as part of DAD [...] there is no need |
2741 | * to delay again before sending the first RS | 2804 | * to delay again before sending the first RS |
2742 | */ | 2805 | */ |
2743 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); | 2806 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
2744 | 2807 | ||
2745 | spin_lock_bh(&ifp->lock); | 2808 | spin_lock_bh(&ifp->lock); |
2746 | ifp->probes = 1; | 2809 | ifp->probes = 1; |
@@ -2776,12 +2839,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2776 | { | 2839 | { |
2777 | struct inet6_ifaddr *ifa = NULL; | 2840 | struct inet6_ifaddr *ifa = NULL; |
2778 | struct if6_iter_state *state = seq->private; | 2841 | struct if6_iter_state *state = seq->private; |
2779 | struct net *net = state->p.net; | 2842 | struct net *net = seq_file_net(seq); |
2780 | 2843 | ||
2781 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 2844 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2782 | ifa = inet6_addr_lst[state->bucket]; | 2845 | ifa = inet6_addr_lst[state->bucket]; |
2783 | 2846 | ||
2784 | while (ifa && ifa->idev->dev->nd_net != net) | 2847 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) |
2785 | ifa = ifa->lst_next; | 2848 | ifa = ifa->lst_next; |
2786 | if (ifa) | 2849 | if (ifa) |
2787 | break; | 2850 | break; |
@@ -2792,12 +2855,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2792 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 2855 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) |
2793 | { | 2856 | { |
2794 | struct if6_iter_state *state = seq->private; | 2857 | struct if6_iter_state *state = seq->private; |
2795 | struct net *net = state->p.net; | 2858 | struct net *net = seq_file_net(seq); |
2796 | 2859 | ||
2797 | ifa = ifa->lst_next; | 2860 | ifa = ifa->lst_next; |
2798 | try_again: | 2861 | try_again: |
2799 | if (ifa) { | 2862 | if (ifa) { |
2800 | if (ifa->idev->dev->nd_net != net) { | 2863 | if (!net_eq(dev_net(ifa->idev->dev), net)) { |
2801 | ifa = ifa->lst_next; | 2864 | ifa = ifa->lst_next; |
2802 | goto try_again; | 2865 | goto try_again; |
2803 | } | 2866 | } |
@@ -2915,9 +2978,9 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
2915 | u8 hash = ipv6_addr_hash(addr); | 2978 | u8 hash = ipv6_addr_hash(addr); |
2916 | read_lock_bh(&addrconf_hash_lock); | 2979 | read_lock_bh(&addrconf_hash_lock); |
2917 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 2980 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { |
2918 | if (ifp->idev->dev->nd_net != net) | 2981 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
2919 | continue; | 2982 | continue; |
2920 | if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && | 2983 | if (ipv6_addr_equal(&ifp->addr, addr) && |
2921 | (ifp->flags & IFA_F_HOMEADDRESS)) { | 2984 | (ifp->flags & IFA_F_HOMEADDRESS)) { |
2922 | ret = 1; | 2985 | ret = 1; |
2923 | break; | 2986 | break; |
@@ -3064,15 +3127,12 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = { | |||
3064 | static int | 3127 | static int |
3065 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 3128 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
3066 | { | 3129 | { |
3067 | struct net *net = skb->sk->sk_net; | 3130 | struct net *net = sock_net(skb->sk); |
3068 | struct ifaddrmsg *ifm; | 3131 | struct ifaddrmsg *ifm; |
3069 | struct nlattr *tb[IFA_MAX+1]; | 3132 | struct nlattr *tb[IFA_MAX+1]; |
3070 | struct in6_addr *pfx; | 3133 | struct in6_addr *pfx; |
3071 | int err; | 3134 | int err; |
3072 | 3135 | ||
3073 | if (net != &init_net) | ||
3074 | return -EINVAL; | ||
3075 | |||
3076 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3136 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3077 | if (err < 0) | 3137 | if (err < 0) |
3078 | return err; | 3138 | return err; |
@@ -3082,7 +3142,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3082 | if (pfx == NULL) | 3142 | if (pfx == NULL) |
3083 | return -EINVAL; | 3143 | return -EINVAL; |
3084 | 3144 | ||
3085 | return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); | 3145 | return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen); |
3086 | } | 3146 | } |
3087 | 3147 | ||
3088 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | 3148 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, |
@@ -3125,7 +3185,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
3125 | static int | 3185 | static int |
3126 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 3186 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
3127 | { | 3187 | { |
3128 | struct net *net = skb->sk->sk_net; | 3188 | struct net *net = sock_net(skb->sk); |
3129 | struct ifaddrmsg *ifm; | 3189 | struct ifaddrmsg *ifm; |
3130 | struct nlattr *tb[IFA_MAX+1]; | 3190 | struct nlattr *tb[IFA_MAX+1]; |
3131 | struct in6_addr *pfx; | 3191 | struct in6_addr *pfx; |
@@ -3135,9 +3195,6 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3135 | u8 ifa_flags; | 3195 | u8 ifa_flags; |
3136 | int err; | 3196 | int err; |
3137 | 3197 | ||
3138 | if (net != &init_net) | ||
3139 | return -EINVAL; | ||
3140 | |||
3141 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3198 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3142 | if (err < 0) | 3199 | if (err < 0) |
3143 | return err; | 3200 | return err; |
@@ -3158,7 +3215,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3158 | valid_lft = INFINITY_LIFE_TIME; | 3215 | valid_lft = INFINITY_LIFE_TIME; |
3159 | } | 3216 | } |
3160 | 3217 | ||
3161 | dev = __dev_get_by_index(&init_net, ifm->ifa_index); | 3218 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3162 | if (dev == NULL) | 3219 | if (dev == NULL) |
3163 | return -ENODEV; | 3220 | return -ENODEV; |
3164 | 3221 | ||
@@ -3171,8 +3228,9 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3171 | * It would be best to check for !NLM_F_CREATE here but | 3228 | * It would be best to check for !NLM_F_CREATE here but |
3172 | * userspace alreay relies on not having to provide this. | 3229 | * userspace alreay relies on not having to provide this. |
3173 | */ | 3230 | */ |
3174 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, | 3231 | return inet6_addr_add(net, ifm->ifa_index, pfx, |
3175 | ifa_flags, preferred_lft, valid_lft); | 3232 | ifm->ifa_prefixlen, ifa_flags, |
3233 | preferred_lft, valid_lft); | ||
3176 | } | 3234 | } |
3177 | 3235 | ||
3178 | if (nlh->nlmsg_flags & NLM_F_EXCL || | 3236 | if (nlh->nlmsg_flags & NLM_F_EXCL || |
@@ -3337,12 +3395,13 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3337 | struct inet6_ifaddr *ifa; | 3395 | struct inet6_ifaddr *ifa; |
3338 | struct ifmcaddr6 *ifmca; | 3396 | struct ifmcaddr6 *ifmca; |
3339 | struct ifacaddr6 *ifaca; | 3397 | struct ifacaddr6 *ifaca; |
3398 | struct net *net = sock_net(skb->sk); | ||
3340 | 3399 | ||
3341 | s_idx = cb->args[0]; | 3400 | s_idx = cb->args[0]; |
3342 | s_ip_idx = ip_idx = cb->args[1]; | 3401 | s_ip_idx = ip_idx = cb->args[1]; |
3343 | 3402 | ||
3344 | idx = 0; | 3403 | idx = 0; |
3345 | for_each_netdev(&init_net, dev) { | 3404 | for_each_netdev(net, dev) { |
3346 | if (idx < s_idx) | 3405 | if (idx < s_idx) |
3347 | goto cont; | 3406 | goto cont; |
3348 | if (idx > s_idx) | 3407 | if (idx > s_idx) |
@@ -3409,42 +3468,30 @@ cont: | |||
3409 | 3468 | ||
3410 | static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3469 | static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3411 | { | 3470 | { |
3412 | struct net *net = skb->sk->sk_net; | ||
3413 | enum addr_type_t type = UNICAST_ADDR; | 3471 | enum addr_type_t type = UNICAST_ADDR; |
3414 | 3472 | ||
3415 | if (net != &init_net) | ||
3416 | return 0; | ||
3417 | |||
3418 | return inet6_dump_addr(skb, cb, type); | 3473 | return inet6_dump_addr(skb, cb, type); |
3419 | } | 3474 | } |
3420 | 3475 | ||
3421 | static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3476 | static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3422 | { | 3477 | { |
3423 | struct net *net = skb->sk->sk_net; | ||
3424 | enum addr_type_t type = MULTICAST_ADDR; | 3478 | enum addr_type_t type = MULTICAST_ADDR; |
3425 | 3479 | ||
3426 | if (net != &init_net) | ||
3427 | return 0; | ||
3428 | |||
3429 | return inet6_dump_addr(skb, cb, type); | 3480 | return inet6_dump_addr(skb, cb, type); |
3430 | } | 3481 | } |
3431 | 3482 | ||
3432 | 3483 | ||
3433 | static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) | 3484 | static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) |
3434 | { | 3485 | { |
3435 | struct net *net = skb->sk->sk_net; | ||
3436 | enum addr_type_t type = ANYCAST_ADDR; | 3486 | enum addr_type_t type = ANYCAST_ADDR; |
3437 | 3487 | ||
3438 | if (net != &init_net) | ||
3439 | return 0; | ||
3440 | |||
3441 | return inet6_dump_addr(skb, cb, type); | 3488 | return inet6_dump_addr(skb, cb, type); |
3442 | } | 3489 | } |
3443 | 3490 | ||
3444 | static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | 3491 | static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, |
3445 | void *arg) | 3492 | void *arg) |
3446 | { | 3493 | { |
3447 | struct net *net = in_skb->sk->sk_net; | 3494 | struct net *net = sock_net(in_skb->sk); |
3448 | struct ifaddrmsg *ifm; | 3495 | struct ifaddrmsg *ifm; |
3449 | struct nlattr *tb[IFA_MAX+1]; | 3496 | struct nlattr *tb[IFA_MAX+1]; |
3450 | struct in6_addr *addr = NULL; | 3497 | struct in6_addr *addr = NULL; |
@@ -3453,9 +3500,6 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3453 | struct sk_buff *skb; | 3500 | struct sk_buff *skb; |
3454 | int err; | 3501 | int err; |
3455 | 3502 | ||
3456 | if (net != &init_net) | ||
3457 | return -EINVAL; | ||
3458 | |||
3459 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3503 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
3460 | if (err < 0) | 3504 | if (err < 0) |
3461 | goto errout; | 3505 | goto errout; |
@@ -3468,7 +3512,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3468 | 3512 | ||
3469 | ifm = nlmsg_data(nlh); | 3513 | ifm = nlmsg_data(nlh); |
3470 | if (ifm->ifa_index) | 3514 | if (ifm->ifa_index) |
3471 | dev = __dev_get_by_index(&init_net, ifm->ifa_index); | 3515 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3472 | 3516 | ||
3473 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3517 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { |
3474 | err = -EADDRNOTAVAIL; | 3518 | err = -EADDRNOTAVAIL; |
@@ -3488,7 +3532,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3488 | kfree_skb(skb); | 3532 | kfree_skb(skb); |
3489 | goto errout_ifa; | 3533 | goto errout_ifa; |
3490 | } | 3534 | } |
3491 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 3535 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
3492 | errout_ifa: | 3536 | errout_ifa: |
3493 | in6_ifa_put(ifa); | 3537 | in6_ifa_put(ifa); |
3494 | errout: | 3538 | errout: |
@@ -3498,6 +3542,7 @@ errout: | |||
3498 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | 3542 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) |
3499 | { | 3543 | { |
3500 | struct sk_buff *skb; | 3544 | struct sk_buff *skb; |
3545 | struct net *net = dev_net(ifa->idev->dev); | ||
3501 | int err = -ENOBUFS; | 3546 | int err = -ENOBUFS; |
3502 | 3547 | ||
3503 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); | 3548 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); |
@@ -3511,10 +3556,10 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3511 | kfree_skb(skb); | 3556 | kfree_skb(skb); |
3512 | goto errout; | 3557 | goto errout; |
3513 | } | 3558 | } |
3514 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3559 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3515 | errout: | 3560 | errout: |
3516 | if (err < 0) | 3561 | if (err < 0) |
3517 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err); | 3562 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
3518 | } | 3563 | } |
3519 | 3564 | ||
3520 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | 3565 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, |
@@ -3556,6 +3601,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
3556 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 3601 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
3557 | array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad; | 3602 | array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad; |
3558 | #endif | 3603 | #endif |
3604 | #ifdef CONFIG_IPV6_MROUTE | ||
3605 | array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding; | ||
3606 | #endif | ||
3559 | } | 3607 | } |
3560 | 3608 | ||
3561 | static inline size_t inet6_if_nlmsg_size(void) | 3609 | static inline size_t inet6_if_nlmsg_size(void) |
@@ -3673,18 +3721,15 @@ nla_put_failure: | |||
3673 | 3721 | ||
3674 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 3722 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
3675 | { | 3723 | { |
3676 | struct net *net = skb->sk->sk_net; | 3724 | struct net *net = sock_net(skb->sk); |
3677 | int idx, err; | 3725 | int idx, err; |
3678 | int s_idx = cb->args[0]; | 3726 | int s_idx = cb->args[0]; |
3679 | struct net_device *dev; | 3727 | struct net_device *dev; |
3680 | struct inet6_dev *idev; | 3728 | struct inet6_dev *idev; |
3681 | 3729 | ||
3682 | if (net != &init_net) | ||
3683 | return 0; | ||
3684 | |||
3685 | read_lock(&dev_base_lock); | 3730 | read_lock(&dev_base_lock); |
3686 | idx = 0; | 3731 | idx = 0; |
3687 | for_each_netdev(&init_net, dev) { | 3732 | for_each_netdev(net, dev) { |
3688 | if (idx < s_idx) | 3733 | if (idx < s_idx) |
3689 | goto cont; | 3734 | goto cont; |
3690 | if ((idev = in6_dev_get(dev)) == NULL) | 3735 | if ((idev = in6_dev_get(dev)) == NULL) |
@@ -3706,6 +3751,7 @@ cont: | |||
3706 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | 3751 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) |
3707 | { | 3752 | { |
3708 | struct sk_buff *skb; | 3753 | struct sk_buff *skb; |
3754 | struct net *net = dev_net(idev->dev); | ||
3709 | int err = -ENOBUFS; | 3755 | int err = -ENOBUFS; |
3710 | 3756 | ||
3711 | skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); | 3757 | skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); |
@@ -3719,10 +3765,10 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3719 | kfree_skb(skb); | 3765 | kfree_skb(skb); |
3720 | goto errout; | 3766 | goto errout; |
3721 | } | 3767 | } |
3722 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3768 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3723 | errout: | 3769 | errout: |
3724 | if (err < 0) | 3770 | if (err < 0) |
3725 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err); | 3771 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
3726 | } | 3772 | } |
3727 | 3773 | ||
3728 | static inline size_t inet6_prefix_nlmsg_size(void) | 3774 | static inline size_t inet6_prefix_nlmsg_size(void) |
@@ -3775,6 +3821,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3775 | struct prefix_info *pinfo) | 3821 | struct prefix_info *pinfo) |
3776 | { | 3822 | { |
3777 | struct sk_buff *skb; | 3823 | struct sk_buff *skb; |
3824 | struct net *net = dev_net(idev->dev); | ||
3778 | int err = -ENOBUFS; | 3825 | int err = -ENOBUFS; |
3779 | 3826 | ||
3780 | skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); | 3827 | skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); |
@@ -3788,10 +3835,10 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3788 | kfree_skb(skb); | 3835 | kfree_skb(skb); |
3789 | goto errout; | 3836 | goto errout; |
3790 | } | 3837 | } |
3791 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3838 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3792 | errout: | 3839 | errout: |
3793 | if (err < 0) | 3840 | if (err < 0) |
3794 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err); | 3841 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
3795 | } | 3842 | } |
3796 | 3843 | ||
3797 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 3844 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
@@ -3887,7 +3934,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table, | |||
3887 | static struct addrconf_sysctl_table | 3934 | static struct addrconf_sysctl_table |
3888 | { | 3935 | { |
3889 | struct ctl_table_header *sysctl_header; | 3936 | struct ctl_table_header *sysctl_header; |
3890 | ctl_table addrconf_vars[__NET_IPV6_MAX]; | 3937 | ctl_table addrconf_vars[DEVCONF_MAX+1]; |
3891 | char *dev_name; | 3938 | char *dev_name; |
3892 | } addrconf_sysctl __read_mostly = { | 3939 | } addrconf_sysctl __read_mostly = { |
3893 | .sysctl_header = NULL, | 3940 | .sysctl_header = NULL, |
@@ -4105,6 +4152,16 @@ static struct addrconf_sysctl_table | |||
4105 | 4152 | ||
4106 | }, | 4153 | }, |
4107 | #endif | 4154 | #endif |
4155 | #ifdef CONFIG_IPV6_MROUTE | ||
4156 | { | ||
4157 | .ctl_name = CTL_UNNUMBERED, | ||
4158 | .procname = "mc_forwarding", | ||
4159 | .data = &ipv6_devconf.mc_forwarding, | ||
4160 | .maxlen = sizeof(int), | ||
4161 | .mode = 0644, | ||
4162 | .proc_handler = &proc_dointvec, | ||
4163 | }, | ||
4164 | #endif | ||
4108 | { | 4165 | { |
4109 | .ctl_name = 0, /* sentinel */ | 4166 | .ctl_name = 0, /* sentinel */ |
4110 | } | 4167 | } |
@@ -4186,7 +4243,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev) | |||
4186 | NET_IPV6_NEIGH, "ipv6", | 4243 | NET_IPV6_NEIGH, "ipv6", |
4187 | &ndisc_ifinfo_sysctl_change, | 4244 | &ndisc_ifinfo_sysctl_change, |
4188 | NULL); | 4245 | NULL); |
4189 | __addrconf_sysctl_register(idev->dev->nd_net, idev->dev->name, | 4246 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, |
4190 | idev->dev->ifindex, idev, &idev->cnf); | 4247 | idev->dev->ifindex, idev, &idev->cnf); |
4191 | } | 4248 | } |
4192 | 4249 | ||
@@ -4281,6 +4338,32 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
4281 | 4338 | ||
4282 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4339 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4283 | 4340 | ||
4341 | |||
4342 | static int addrconf_net_init(struct net *net) | ||
4343 | { | ||
4344 | return 0; | ||
4345 | } | ||
4346 | |||
4347 | static void addrconf_net_exit(struct net *net) | ||
4348 | { | ||
4349 | struct net_device *dev; | ||
4350 | |||
4351 | rtnl_lock(); | ||
4352 | /* clean dev list */ | ||
4353 | for_each_netdev(net, dev) { | ||
4354 | if (__in6_dev_get(dev) == NULL) | ||
4355 | continue; | ||
4356 | addrconf_ifdown(dev, 1); | ||
4357 | } | ||
4358 | addrconf_ifdown(net->loopback_dev, 2); | ||
4359 | rtnl_unlock(); | ||
4360 | } | ||
4361 | |||
4362 | static struct pernet_operations addrconf_net_ops = { | ||
4363 | .init = addrconf_net_init, | ||
4364 | .exit = addrconf_net_exit, | ||
4365 | }; | ||
4366 | |||
4284 | /* | 4367 | /* |
4285 | * Init / cleanup code | 4368 | * Init / cleanup code |
4286 | */ | 4369 | */ |
@@ -4322,14 +4405,9 @@ int __init addrconf_init(void) | |||
4322 | if (err) | 4405 | if (err) |
4323 | goto errlo; | 4406 | goto errlo; |
4324 | 4407 | ||
4325 | ip6_null_entry.u.dst.dev = init_net.loopback_dev; | 4408 | err = register_pernet_device(&addrconf_net_ops); |
4326 | ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | 4409 | if (err) |
4327 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 4410 | return err; |
4328 | ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev; | ||
4329 | ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4330 | ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev; | ||
4331 | ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
4332 | #endif | ||
4333 | 4411 | ||
4334 | register_netdevice_notifier(&ipv6_dev_notf); | 4412 | register_netdevice_notifier(&ipv6_dev_notf); |
4335 | 4413 | ||
@@ -4359,31 +4437,19 @@ errlo: | |||
4359 | 4437 | ||
4360 | void addrconf_cleanup(void) | 4438 | void addrconf_cleanup(void) |
4361 | { | 4439 | { |
4362 | struct net_device *dev; | ||
4363 | struct inet6_ifaddr *ifa; | 4440 | struct inet6_ifaddr *ifa; |
4364 | int i; | 4441 | int i; |
4365 | 4442 | ||
4366 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4443 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4444 | unregister_pernet_device(&addrconf_net_ops); | ||
4367 | 4445 | ||
4368 | unregister_pernet_subsys(&addrconf_ops); | 4446 | unregister_pernet_subsys(&addrconf_ops); |
4369 | 4447 | ||
4370 | rtnl_lock(); | 4448 | rtnl_lock(); |
4371 | 4449 | ||
4372 | /* | 4450 | /* |
4373 | * clean dev list. | ||
4374 | */ | ||
4375 | |||
4376 | for_each_netdev(&init_net, dev) { | ||
4377 | if (__in6_dev_get(dev) == NULL) | ||
4378 | continue; | ||
4379 | addrconf_ifdown(dev, 1); | ||
4380 | } | ||
4381 | addrconf_ifdown(init_net.loopback_dev, 2); | ||
4382 | |||
4383 | /* | ||
4384 | * Check hash table. | 4451 | * Check hash table. |
4385 | */ | 4452 | */ |
4386 | |||
4387 | write_lock_bh(&addrconf_hash_lock); | 4453 | write_lock_bh(&addrconf_hash_lock); |
4388 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4454 | for (i=0; i < IN6_ADDR_HSIZE; i++) { |
4389 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4455 | for (ifa=inet6_addr_lst[i]; ifa; ) { |
@@ -4400,6 +4466,7 @@ void addrconf_cleanup(void) | |||
4400 | write_unlock_bh(&addrconf_hash_lock); | 4466 | write_unlock_bh(&addrconf_hash_lock); |
4401 | 4467 | ||
4402 | del_timer(&addr_chk_timer); | 4468 | del_timer(&addr_chk_timer); |
4403 | |||
4404 | rtnl_unlock(); | 4469 | rtnl_unlock(); |
4470 | |||
4471 | unregister_pernet_subsys(&addrconf_net_ops); | ||
4405 | } | 4472 | } |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index a3c5a72218fd..9bfa8846f262 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -58,6 +58,7 @@ static struct ip6addrlbl_table | |||
58 | * ::ffff:0:0/96 V4MAPPED 4 | 58 | * ::ffff:0:0/96 V4MAPPED 4 |
59 | * fc00::/7 N/A 5 ULA (RFC 4193) | 59 | * fc00::/7 N/A 5 ULA (RFC 4193) |
60 | * 2001::/32 N/A 6 Teredo (RFC 4380) | 60 | * 2001::/32 N/A 6 Teredo (RFC 4380) |
61 | * 2001:10::/28 N/A 7 ORCHID (RFC 4843) | ||
61 | * | 62 | * |
62 | * Note: 0xffffffff is used if we do not have any policies. | 63 | * Note: 0xffffffff is used if we do not have any policies. |
63 | */ | 64 | */ |
@@ -85,6 +86,10 @@ static const __initdata struct ip6addrlbl_init_table | |||
85 | .prefix = &(struct in6_addr){{{ 0x20, 0x01 }}}, | 86 | .prefix = &(struct in6_addr){{{ 0x20, 0x01 }}}, |
86 | .prefixlen = 32, | 87 | .prefixlen = 32, |
87 | .label = 6, | 88 | .label = 6, |
89 | },{ /* 2001:10::/28 */ | ||
90 | .prefix = &(struct in6_addr){{{ 0x20, 0x01, 0x00, 0x10 }}}, | ||
91 | .prefixlen = 28, | ||
92 | .label = 7, | ||
88 | },{ /* ::ffff:0:0 */ | 93 | },{ /* ::ffff:0:0 */ |
89 | .prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}}, | 94 | .prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}}, |
90 | .prefixlen = 96, | 95 | .prefixlen = 96, |
@@ -161,7 +166,7 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | |||
161 | rcu_read_unlock(); | 166 | rcu_read_unlock(); |
162 | 167 | ||
163 | ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n", | 168 | ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n", |
164 | __FUNCTION__, | 169 | __func__, |
165 | NIP6(*addr), type, ifindex, | 170 | NIP6(*addr), type, ifindex, |
166 | label); | 171 | label); |
167 | 172 | ||
@@ -177,7 +182,7 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, | |||
177 | int addrtype; | 182 | int addrtype; |
178 | 183 | ||
179 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n", | 184 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n", |
180 | __FUNCTION__, | 185 | __func__, |
181 | NIP6(*prefix), prefixlen, | 186 | NIP6(*prefix), prefixlen, |
182 | ifindex, | 187 | ifindex, |
183 | (unsigned int)label); | 188 | (unsigned int)label); |
@@ -221,7 +226,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
221 | int ret = 0; | 226 | int ret = 0; |
222 | 227 | ||
223 | ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", | 228 | ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", |
224 | __FUNCTION__, | 229 | __func__, |
225 | newp, replace); | 230 | newp, replace); |
226 | 231 | ||
227 | if (hlist_empty(&ip6addrlbl_table.head)) { | 232 | if (hlist_empty(&ip6addrlbl_table.head)) { |
@@ -263,7 +268,7 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | |||
263 | int ret = 0; | 268 | int ret = 0; |
264 | 269 | ||
265 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n", | 270 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n", |
266 | __FUNCTION__, | 271 | __func__, |
267 | NIP6(*prefix), prefixlen, | 272 | NIP6(*prefix), prefixlen, |
268 | ifindex, | 273 | ifindex, |
269 | (unsigned int)label, | 274 | (unsigned int)label, |
@@ -289,7 +294,7 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
289 | int ret = -ESRCH; | 294 | int ret = -ESRCH; |
290 | 295 | ||
291 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", | 296 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", |
292 | __FUNCTION__, | 297 | __func__, |
293 | NIP6(*prefix), prefixlen, | 298 | NIP6(*prefix), prefixlen, |
294 | ifindex); | 299 | ifindex); |
295 | 300 | ||
@@ -313,7 +318,7 @@ static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
313 | int ret; | 318 | int ret; |
314 | 319 | ||
315 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", | 320 | ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n", |
316 | __FUNCTION__, | 321 | __func__, |
317 | NIP6(*prefix), prefixlen, | 322 | NIP6(*prefix), prefixlen, |
318 | ifindex); | 323 | ifindex); |
319 | 324 | ||
@@ -330,7 +335,7 @@ static __init int ip6addrlbl_init(void) | |||
330 | int err = 0; | 335 | int err = 0; |
331 | int i; | 336 | int i; |
332 | 337 | ||
333 | ADDRLABEL(KERN_DEBUG "%s()\n", __FUNCTION__); | 338 | ADDRLABEL(KERN_DEBUG "%s()\n", __func__); |
334 | 339 | ||
335 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { | 340 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { |
336 | int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix, | 341 | int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix, |
@@ -359,7 +364,7 @@ static const struct nla_policy ifal_policy[IFAL_MAX+1] = { | |||
359 | static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | 364 | static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, |
360 | void *arg) | 365 | void *arg) |
361 | { | 366 | { |
362 | struct net *net = skb->sk->sk_net; | 367 | struct net *net = sock_net(skb->sk); |
363 | struct ifaddrlblmsg *ifal; | 368 | struct ifaddrlblmsg *ifal; |
364 | struct nlattr *tb[IFAL_MAX+1]; | 369 | struct nlattr *tb[IFAL_MAX+1]; |
365 | struct in6_addr *pfx; | 370 | struct in6_addr *pfx; |
@@ -447,7 +452,7 @@ static int ip6addrlbl_fill(struct sk_buff *skb, | |||
447 | 452 | ||
448 | static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) | 453 | static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) |
449 | { | 454 | { |
450 | struct net *net = skb->sk->sk_net; | 455 | struct net *net = sock_net(skb->sk); |
451 | struct ip6addrlbl_entry *p; | 456 | struct ip6addrlbl_entry *p; |
452 | struct hlist_node *pos; | 457 | struct hlist_node *pos; |
453 | int idx = 0, s_idx = cb->args[0]; | 458 | int idx = 0, s_idx = cb->args[0]; |
@@ -485,7 +490,7 @@ static inline int ip6addrlbl_msgsize(void) | |||
485 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | 490 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, |
486 | void *arg) | 491 | void *arg) |
487 | { | 492 | { |
488 | struct net *net = in_skb->sk->sk_net; | 493 | struct net *net = sock_net(in_skb->sk); |
489 | struct ifaddrlblmsg *ifal; | 494 | struct ifaddrlblmsg *ifal; |
490 | struct nlattr *tb[IFAL_MAX+1]; | 495 | struct nlattr *tb[IFAL_MAX+1]; |
491 | struct in6_addr *addr; | 496 | struct in6_addr *addr; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index f0aa97738746..3c6aafb02183 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -61,6 +61,9 @@ | |||
61 | 61 | ||
62 | #include <asm/uaccess.h> | 62 | #include <asm/uaccess.h> |
63 | #include <asm/system.h> | 63 | #include <asm/system.h> |
64 | #ifdef CONFIG_IPV6_MROUTE | ||
65 | #include <linux/mroute6.h> | ||
66 | #endif | ||
64 | 67 | ||
65 | MODULE_AUTHOR("Cast of dozens"); | 68 | MODULE_AUTHOR("Cast of dozens"); |
66 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); | 69 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); |
@@ -92,9 +95,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol) | |||
92 | int try_loading_module = 0; | 95 | int try_loading_module = 0; |
93 | int err; | 96 | int err; |
94 | 97 | ||
95 | if (net != &init_net) | ||
96 | return -EAFNOSUPPORT; | ||
97 | |||
98 | if (sock->type != SOCK_RAW && | 98 | if (sock->type != SOCK_RAW && |
99 | sock->type != SOCK_DGRAM && | 99 | sock->type != SOCK_DGRAM && |
100 | !inet_ehash_secret) | 100 | !inet_ehash_secret) |
@@ -248,6 +248,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
248 | struct sock *sk = sock->sk; | 248 | struct sock *sk = sock->sk; |
249 | struct inet_sock *inet = inet_sk(sk); | 249 | struct inet_sock *inet = inet_sk(sk); |
250 | struct ipv6_pinfo *np = inet6_sk(sk); | 250 | struct ipv6_pinfo *np = inet6_sk(sk); |
251 | struct net *net = sock_net(sk); | ||
251 | __be32 v4addr = 0; | 252 | __be32 v4addr = 0; |
252 | unsigned short snum; | 253 | unsigned short snum; |
253 | int addr_type = 0; | 254 | int addr_type = 0; |
@@ -278,7 +279,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
278 | /* Check if the address belongs to the host. */ | 279 | /* Check if the address belongs to the host. */ |
279 | if (addr_type == IPV6_ADDR_MAPPED) { | 280 | if (addr_type == IPV6_ADDR_MAPPED) { |
280 | v4addr = addr->sin6_addr.s6_addr32[3]; | 281 | v4addr = addr->sin6_addr.s6_addr32[3]; |
281 | if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) { | 282 | if (inet_addr_type(net, v4addr) != RTN_LOCAL) { |
282 | err = -EADDRNOTAVAIL; | 283 | err = -EADDRNOTAVAIL; |
283 | goto out; | 284 | goto out; |
284 | } | 285 | } |
@@ -300,7 +301,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
300 | err = -EINVAL; | 301 | err = -EINVAL; |
301 | goto out; | 302 | goto out; |
302 | } | 303 | } |
303 | dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); | 304 | dev = dev_get_by_index(net, sk->sk_bound_dev_if); |
304 | if (!dev) { | 305 | if (!dev) { |
305 | err = -ENODEV; | 306 | err = -ENODEV; |
306 | goto out; | 307 | goto out; |
@@ -312,7 +313,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
312 | */ | 313 | */ |
313 | v4addr = LOOPBACK4_IPV6; | 314 | v4addr = LOOPBACK4_IPV6; |
314 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 315 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
315 | if (!ipv6_chk_addr(&init_net, &addr->sin6_addr, | 316 | if (!ipv6_chk_addr(net, &addr->sin6_addr, |
316 | dev, 0)) { | 317 | dev, 0)) { |
317 | if (dev) | 318 | if (dev) |
318 | dev_put(dev); | 319 | dev_put(dev); |
@@ -440,6 +441,7 @@ EXPORT_SYMBOL(inet6_getname); | |||
440 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 441 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
441 | { | 442 | { |
442 | struct sock *sk = sock->sk; | 443 | struct sock *sk = sock->sk; |
444 | struct net *net = sock_net(sk); | ||
443 | 445 | ||
444 | switch(cmd) | 446 | switch(cmd) |
445 | { | 447 | { |
@@ -452,14 +454,14 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
452 | case SIOCADDRT: | 454 | case SIOCADDRT: |
453 | case SIOCDELRT: | 455 | case SIOCDELRT: |
454 | 456 | ||
455 | return(ipv6_route_ioctl(cmd,(void __user *)arg)); | 457 | return(ipv6_route_ioctl(net, cmd, (void __user *)arg)); |
456 | 458 | ||
457 | case SIOCSIFADDR: | 459 | case SIOCSIFADDR: |
458 | return addrconf_add_ifaddr((void __user *) arg); | 460 | return addrconf_add_ifaddr(net, (void __user *) arg); |
459 | case SIOCDIFADDR: | 461 | case SIOCDIFADDR: |
460 | return addrconf_del_ifaddr((void __user *) arg); | 462 | return addrconf_del_ifaddr(net, (void __user *) arg); |
461 | case SIOCSIFDSTADDR: | 463 | case SIOCSIFDSTADDR: |
462 | return addrconf_set_dstaddr((void __user *) arg); | 464 | return addrconf_set_dstaddr(net, (void __user *) arg); |
463 | default: | 465 | default: |
464 | if (!sk->sk_prot->ioctl) | 466 | if (!sk->sk_prot->ioctl) |
465 | return -ENOIOCTLCMD; | 467 | return -ENOIOCTLCMD; |
@@ -678,6 +680,129 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) | |||
678 | 680 | ||
679 | EXPORT_SYMBOL_GPL(ipv6_opt_accepted); | 681 | EXPORT_SYMBOL_GPL(ipv6_opt_accepted); |
680 | 682 | ||
683 | static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb, | ||
684 | int proto) | ||
685 | { | ||
686 | struct inet6_protocol *ops = NULL; | ||
687 | |||
688 | for (;;) { | ||
689 | struct ipv6_opt_hdr *opth; | ||
690 | int len; | ||
691 | |||
692 | if (proto != NEXTHDR_HOP) { | ||
693 | ops = rcu_dereference(inet6_protos[proto]); | ||
694 | |||
695 | if (unlikely(!ops)) | ||
696 | break; | ||
697 | |||
698 | if (!(ops->flags & INET6_PROTO_GSO_EXTHDR)) | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | if (unlikely(!pskb_may_pull(skb, 8))) | ||
703 | break; | ||
704 | |||
705 | opth = (void *)skb->data; | ||
706 | len = ipv6_optlen(opth); | ||
707 | |||
708 | if (unlikely(!pskb_may_pull(skb, len))) | ||
709 | break; | ||
710 | |||
711 | proto = opth->nexthdr; | ||
712 | __skb_pull(skb, len); | ||
713 | } | ||
714 | |||
715 | return ops; | ||
716 | } | ||
717 | |||
718 | static int ipv6_gso_send_check(struct sk_buff *skb) | ||
719 | { | ||
720 | struct ipv6hdr *ipv6h; | ||
721 | struct inet6_protocol *ops; | ||
722 | int err = -EINVAL; | ||
723 | |||
724 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
725 | goto out; | ||
726 | |||
727 | ipv6h = ipv6_hdr(skb); | ||
728 | __skb_pull(skb, sizeof(*ipv6h)); | ||
729 | err = -EPROTONOSUPPORT; | ||
730 | |||
731 | rcu_read_lock(); | ||
732 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | ||
733 | if (likely(ops && ops->gso_send_check)) { | ||
734 | skb_reset_transport_header(skb); | ||
735 | err = ops->gso_send_check(skb); | ||
736 | } | ||
737 | rcu_read_unlock(); | ||
738 | |||
739 | out: | ||
740 | return err; | ||
741 | } | ||
742 | |||
743 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | ||
744 | { | ||
745 | struct sk_buff *segs = ERR_PTR(-EINVAL); | ||
746 | struct ipv6hdr *ipv6h; | ||
747 | struct inet6_protocol *ops; | ||
748 | |||
749 | if (!(features & NETIF_F_V6_CSUM)) | ||
750 | features &= ~NETIF_F_SG; | ||
751 | |||
752 | if (unlikely(skb_shinfo(skb)->gso_type & | ||
753 | ~(SKB_GSO_UDP | | ||
754 | SKB_GSO_DODGY | | ||
755 | SKB_GSO_TCP_ECN | | ||
756 | SKB_GSO_TCPV6 | | ||
757 | 0))) | ||
758 | goto out; | ||
759 | |||
760 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
761 | goto out; | ||
762 | |||
763 | ipv6h = ipv6_hdr(skb); | ||
764 | __skb_pull(skb, sizeof(*ipv6h)); | ||
765 | segs = ERR_PTR(-EPROTONOSUPPORT); | ||
766 | |||
767 | rcu_read_lock(); | ||
768 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | ||
769 | if (likely(ops && ops->gso_segment)) { | ||
770 | skb_reset_transport_header(skb); | ||
771 | segs = ops->gso_segment(skb, features); | ||
772 | } | ||
773 | rcu_read_unlock(); | ||
774 | |||
775 | if (unlikely(IS_ERR(segs))) | ||
776 | goto out; | ||
777 | |||
778 | for (skb = segs; skb; skb = skb->next) { | ||
779 | ipv6h = ipv6_hdr(skb); | ||
780 | ipv6h->payload_len = htons(skb->len - skb->mac_len - | ||
781 | sizeof(*ipv6h)); | ||
782 | } | ||
783 | |||
784 | out: | ||
785 | return segs; | ||
786 | } | ||
787 | |||
788 | static struct packet_type ipv6_packet_type = { | ||
789 | .type = __constant_htons(ETH_P_IPV6), | ||
790 | .func = ipv6_rcv, | ||
791 | .gso_send_check = ipv6_gso_send_check, | ||
792 | .gso_segment = ipv6_gso_segment, | ||
793 | }; | ||
794 | |||
795 | static int __init ipv6_packet_init(void) | ||
796 | { | ||
797 | dev_add_pack(&ipv6_packet_type); | ||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static void ipv6_packet_cleanup(void) | ||
802 | { | ||
803 | dev_remove_pack(&ipv6_packet_type); | ||
804 | } | ||
805 | |||
681 | static int __init init_ipv6_mibs(void) | 806 | static int __init init_ipv6_mibs(void) |
682 | { | 807 | { |
683 | if (snmp_mib_init((void **)ipv6_statistics, | 808 | if (snmp_mib_init((void **)ipv6_statistics, |
@@ -720,6 +845,8 @@ static void cleanup_ipv6_mibs(void) | |||
720 | 845 | ||
721 | static int inet6_net_init(struct net *net) | 846 | static int inet6_net_init(struct net *net) |
722 | { | 847 | { |
848 | int err = 0; | ||
849 | |||
723 | net->ipv6.sysctl.bindv6only = 0; | 850 | net->ipv6.sysctl.bindv6only = 0; |
724 | net->ipv6.sysctl.flush_delay = 0; | 851 | net->ipv6.sysctl.flush_delay = 0; |
725 | net->ipv6.sysctl.ip6_rt_max_size = 4096; | 852 | net->ipv6.sysctl.ip6_rt_max_size = 4096; |
@@ -731,12 +858,36 @@ static int inet6_net_init(struct net *net) | |||
731 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; | 858 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; |
732 | net->ipv6.sysctl.icmpv6_time = 1*HZ; | 859 | net->ipv6.sysctl.icmpv6_time = 1*HZ; |
733 | 860 | ||
734 | return 0; | 861 | #ifdef CONFIG_PROC_FS |
862 | err = udp6_proc_init(net); | ||
863 | if (err) | ||
864 | goto out; | ||
865 | err = tcp6_proc_init(net); | ||
866 | if (err) | ||
867 | goto proc_tcp6_fail; | ||
868 | err = ac6_proc_init(net); | ||
869 | if (err) | ||
870 | goto proc_ac6_fail; | ||
871 | out: | ||
872 | #endif | ||
873 | return err; | ||
874 | |||
875 | #ifdef CONFIG_PROC_FS | ||
876 | proc_ac6_fail: | ||
877 | tcp6_proc_exit(net); | ||
878 | proc_tcp6_fail: | ||
879 | udp6_proc_exit(net); | ||
880 | goto out; | ||
881 | #endif | ||
735 | } | 882 | } |
736 | 883 | ||
737 | static void inet6_net_exit(struct net *net) | 884 | static void inet6_net_exit(struct net *net) |
738 | { | 885 | { |
739 | return; | 886 | #ifdef CONFIG_PROC_FS |
887 | udp6_proc_exit(net); | ||
888 | tcp6_proc_exit(net); | ||
889 | ac6_proc_exit(net); | ||
890 | #endif | ||
740 | } | 891 | } |
741 | 892 | ||
742 | static struct pernet_operations inet6_net_ops = { | 893 | static struct pernet_operations inet6_net_ops = { |
@@ -802,19 +953,16 @@ static int __init inet6_init(void) | |||
802 | err = register_pernet_subsys(&inet6_net_ops); | 953 | err = register_pernet_subsys(&inet6_net_ops); |
803 | if (err) | 954 | if (err) |
804 | goto register_pernet_fail; | 955 | goto register_pernet_fail; |
805 | 956 | 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) | 957 | if (err) |
813 | goto icmp_fail; | 958 | goto icmp_fail; |
814 | err = ndisc_init(&inet6_family_ops); | 959 | #ifdef CONFIG_IPV6_MROUTE |
960 | ip6_mr_init(); | ||
961 | #endif | ||
962 | err = ndisc_init(); | ||
815 | if (err) | 963 | if (err) |
816 | goto ndisc_fail; | 964 | goto ndisc_fail; |
817 | err = igmp6_init(&inet6_family_ops); | 965 | err = igmp6_init(); |
818 | if (err) | 966 | if (err) |
819 | goto igmp_fail; | 967 | goto igmp_fail; |
820 | err = ipv6_netfilter_init(); | 968 | err = ipv6_netfilter_init(); |
@@ -825,17 +973,10 @@ static int __init inet6_init(void) | |||
825 | err = -ENOMEM; | 973 | err = -ENOMEM; |
826 | if (raw6_proc_init()) | 974 | if (raw6_proc_init()) |
827 | goto proc_raw6_fail; | 975 | 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()) | 976 | if (udplite6_proc_init()) |
833 | goto proc_udplite6_fail; | 977 | goto proc_udplite6_fail; |
834 | if (ipv6_misc_proc_init()) | 978 | if (ipv6_misc_proc_init()) |
835 | goto proc_misc6_fail; | 979 | goto proc_misc6_fail; |
836 | |||
837 | if (ac6_proc_init()) | ||
838 | goto proc_anycast6_fail; | ||
839 | if (if6_proc_init()) | 980 | if (if6_proc_init()) |
840 | goto proc_if6_fail; | 981 | goto proc_if6_fail; |
841 | #endif | 982 | #endif |
@@ -874,9 +1015,19 @@ static int __init inet6_init(void) | |||
874 | err = ipv6_packet_init(); | 1015 | err = ipv6_packet_init(); |
875 | if (err) | 1016 | if (err) |
876 | goto ipv6_packet_fail; | 1017 | goto ipv6_packet_fail; |
1018 | |||
1019 | #ifdef CONFIG_SYSCTL | ||
1020 | err = ipv6_sysctl_register(); | ||
1021 | if (err) | ||
1022 | goto sysctl_fail; | ||
1023 | #endif | ||
877 | out: | 1024 | out: |
878 | return err; | 1025 | return err; |
879 | 1026 | ||
1027 | #ifdef CONFIG_SYSCTL | ||
1028 | sysctl_fail: | ||
1029 | ipv6_packet_cleanup(); | ||
1030 | #endif | ||
880 | ipv6_packet_fail: | 1031 | ipv6_packet_fail: |
881 | tcpv6_exit(); | 1032 | tcpv6_exit(); |
882 | tcpv6_fail: | 1033 | tcpv6_fail: |
@@ -897,16 +1048,10 @@ ip6_route_fail: | |||
897 | #ifdef CONFIG_PROC_FS | 1048 | #ifdef CONFIG_PROC_FS |
898 | if6_proc_exit(); | 1049 | if6_proc_exit(); |
899 | proc_if6_fail: | 1050 | proc_if6_fail: |
900 | ac6_proc_exit(); | ||
901 | proc_anycast6_fail: | ||
902 | ipv6_misc_proc_exit(); | 1051 | ipv6_misc_proc_exit(); |
903 | proc_misc6_fail: | 1052 | proc_misc6_fail: |
904 | udplite6_proc_exit(); | 1053 | udplite6_proc_exit(); |
905 | proc_udplite6_fail: | 1054 | proc_udplite6_fail: |
906 | udp6_proc_exit(); | ||
907 | proc_udp6_fail: | ||
908 | tcp6_proc_exit(); | ||
909 | proc_tcp6_fail: | ||
910 | raw6_proc_exit(); | 1055 | raw6_proc_exit(); |
911 | proc_raw6_fail: | 1056 | proc_raw6_fail: |
912 | #endif | 1057 | #endif |
@@ -918,10 +1063,6 @@ igmp_fail: | |||
918 | ndisc_fail: | 1063 | ndisc_fail: |
919 | icmpv6_cleanup(); | 1064 | icmpv6_cleanup(); |
920 | icmp_fail: | 1065 | icmp_fail: |
921 | #ifdef CONFIG_SYSCTL | ||
922 | ipv6_sysctl_unregister(); | ||
923 | sysctl_fail: | ||
924 | #endif | ||
925 | unregister_pernet_subsys(&inet6_net_ops); | 1066 | unregister_pernet_subsys(&inet6_net_ops); |
926 | register_pernet_fail: | 1067 | register_pernet_fail: |
927 | cleanup_ipv6_mibs(); | 1068 | cleanup_ipv6_mibs(); |
@@ -949,6 +1090,9 @@ static void __exit inet6_exit(void) | |||
949 | /* Disallow any further netlink messages */ | 1090 | /* Disallow any further netlink messages */ |
950 | rtnl_unregister_all(PF_INET6); | 1091 | rtnl_unregister_all(PF_INET6); |
951 | 1092 | ||
1093 | #ifdef CONFIG_SYSCTL | ||
1094 | ipv6_sysctl_unregister(); | ||
1095 | #endif | ||
952 | udpv6_exit(); | 1096 | udpv6_exit(); |
953 | udplitev6_exit(); | 1097 | udplitev6_exit(); |
954 | tcpv6_exit(); | 1098 | tcpv6_exit(); |
@@ -964,11 +1108,8 @@ static void __exit inet6_exit(void) | |||
964 | 1108 | ||
965 | /* Cleanup code parts. */ | 1109 | /* Cleanup code parts. */ |
966 | if6_proc_exit(); | 1110 | if6_proc_exit(); |
967 | ac6_proc_exit(); | ||
968 | ipv6_misc_proc_exit(); | 1111 | ipv6_misc_proc_exit(); |
969 | udplite6_proc_exit(); | 1112 | udplite6_proc_exit(); |
970 | udp6_proc_exit(); | ||
971 | tcp6_proc_exit(); | ||
972 | raw6_proc_exit(); | 1113 | raw6_proc_exit(); |
973 | #endif | 1114 | #endif |
974 | ipv6_netfilter_fini(); | 1115 | ipv6_netfilter_fini(); |
@@ -976,9 +1117,7 @@ static void __exit inet6_exit(void) | |||
976 | ndisc_cleanup(); | 1117 | ndisc_cleanup(); |
977 | icmpv6_cleanup(); | 1118 | icmpv6_cleanup(); |
978 | rawv6_exit(); | 1119 | rawv6_exit(); |
979 | #ifdef CONFIG_SYSCTL | 1120 | |
980 | ipv6_sysctl_unregister(); | ||
981 | #endif | ||
982 | unregister_pernet_subsys(&inet6_net_ops); | 1121 | unregister_pernet_subsys(&inet6_net_ops); |
983 | cleanup_ipv6_mibs(); | 1122 | cleanup_ipv6_mibs(); |
984 | proto_unregister(&rawv6_prot); | 1123 | proto_unregister(&rawv6_prot); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index e5f56c953b58..4e1b29fabdf0 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -48,29 +48,6 @@ static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr); | |||
48 | /* Big ac list lock for all the sockets */ | 48 | /* Big ac list lock for all the sockets */ |
49 | static DEFINE_RWLOCK(ipv6_sk_ac_lock); | 49 | static DEFINE_RWLOCK(ipv6_sk_ac_lock); |
50 | 50 | ||
51 | static int | ||
52 | ip6_onlink(struct in6_addr *addr, struct net_device *dev) | ||
53 | { | ||
54 | struct inet6_dev *idev; | ||
55 | struct inet6_ifaddr *ifa; | ||
56 | int onlink; | ||
57 | |||
58 | onlink = 0; | ||
59 | rcu_read_lock(); | ||
60 | idev = __in6_dev_get(dev); | ||
61 | if (idev) { | ||
62 | read_lock_bh(&idev->lock); | ||
63 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | ||
64 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | ||
65 | ifa->prefix_len); | ||
66 | if (onlink) | ||
67 | break; | ||
68 | } | ||
69 | read_unlock_bh(&idev->lock); | ||
70 | } | ||
71 | rcu_read_unlock(); | ||
72 | return onlink; | ||
73 | } | ||
74 | 51 | ||
75 | /* | 52 | /* |
76 | * socket join an anycast group | 53 | * socket join an anycast group |
@@ -82,6 +59,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
82 | struct net_device *dev = NULL; | 59 | struct net_device *dev = NULL; |
83 | struct inet6_dev *idev; | 60 | struct inet6_dev *idev; |
84 | struct ipv6_ac_socklist *pac; | 61 | struct ipv6_ac_socklist *pac; |
62 | struct net *net = sock_net(sk); | ||
85 | int ishost = !ipv6_devconf.forwarding; | 63 | int ishost = !ipv6_devconf.forwarding; |
86 | int err = 0; | 64 | int err = 0; |
87 | 65 | ||
@@ -89,7 +67,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
89 | return -EPERM; | 67 | return -EPERM; |
90 | if (ipv6_addr_is_multicast(addr)) | 68 | if (ipv6_addr_is_multicast(addr)) |
91 | return -EINVAL; | 69 | return -EINVAL; |
92 | if (ipv6_chk_addr(&init_net, addr, NULL, 0)) | 70 | if (ipv6_chk_addr(net, addr, NULL, 0)) |
93 | return -EINVAL; | 71 | return -EINVAL; |
94 | 72 | ||
95 | pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); | 73 | pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); |
@@ -101,7 +79,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
101 | if (ifindex == 0) { | 79 | if (ifindex == 0) { |
102 | struct rt6_info *rt; | 80 | struct rt6_info *rt; |
103 | 81 | ||
104 | rt = rt6_lookup(addr, NULL, 0, 0); | 82 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
105 | if (rt) { | 83 | if (rt) { |
106 | dev = rt->rt6i_dev; | 84 | dev = rt->rt6i_dev; |
107 | dev_hold(dev); | 85 | dev_hold(dev); |
@@ -112,10 +90,10 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
112 | } else { | 90 | } else { |
113 | /* router, no matching interface: just pick one */ | 91 | /* router, no matching interface: just pick one */ |
114 | 92 | ||
115 | dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK); | 93 | dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK); |
116 | } | 94 | } |
117 | } else | 95 | } else |
118 | dev = dev_get_by_index(&init_net, ifindex); | 96 | dev = dev_get_by_index(net, ifindex); |
119 | 97 | ||
120 | if (dev == NULL) { | 98 | if (dev == NULL) { |
121 | err = -ENODEV; | 99 | err = -ENODEV; |
@@ -141,7 +119,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
141 | * This obviates the need for propagating anycast routes while | 119 | * This obviates the need for propagating anycast routes while |
142 | * still allowing some non-router anycast participation. | 120 | * still allowing some non-router anycast participation. |
143 | */ | 121 | */ |
144 | if (!ip6_onlink(addr, dev)) { | 122 | if (!ipv6_chk_prefix(addr, dev)) { |
145 | if (ishost) | 123 | if (ishost) |
146 | err = -EADDRNOTAVAIL; | 124 | err = -EADDRNOTAVAIL; |
147 | if (err) | 125 | if (err) |
@@ -176,6 +154,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
176 | struct ipv6_pinfo *np = inet6_sk(sk); | 154 | struct ipv6_pinfo *np = inet6_sk(sk); |
177 | struct net_device *dev; | 155 | struct net_device *dev; |
178 | struct ipv6_ac_socklist *pac, *prev_pac; | 156 | struct ipv6_ac_socklist *pac, *prev_pac; |
157 | struct net *net = sock_net(sk); | ||
179 | 158 | ||
180 | write_lock_bh(&ipv6_sk_ac_lock); | 159 | write_lock_bh(&ipv6_sk_ac_lock); |
181 | prev_pac = NULL; | 160 | prev_pac = NULL; |
@@ -196,7 +175,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
196 | 175 | ||
197 | write_unlock_bh(&ipv6_sk_ac_lock); | 176 | write_unlock_bh(&ipv6_sk_ac_lock); |
198 | 177 | ||
199 | dev = dev_get_by_index(&init_net, pac->acl_ifindex); | 178 | dev = dev_get_by_index(net, pac->acl_ifindex); |
200 | if (dev) { | 179 | if (dev) { |
201 | ipv6_dev_ac_dec(dev, &pac->acl_addr); | 180 | ipv6_dev_ac_dec(dev, &pac->acl_addr); |
202 | dev_put(dev); | 181 | dev_put(dev); |
@@ -210,6 +189,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
210 | struct ipv6_pinfo *np = inet6_sk(sk); | 189 | struct ipv6_pinfo *np = inet6_sk(sk); |
211 | struct net_device *dev = NULL; | 190 | struct net_device *dev = NULL; |
212 | struct ipv6_ac_socklist *pac; | 191 | struct ipv6_ac_socklist *pac; |
192 | struct net *net = sock_net(sk); | ||
213 | int prev_index; | 193 | int prev_index; |
214 | 194 | ||
215 | write_lock_bh(&ipv6_sk_ac_lock); | 195 | write_lock_bh(&ipv6_sk_ac_lock); |
@@ -224,7 +204,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
224 | if (pac->acl_ifindex != prev_index) { | 204 | if (pac->acl_ifindex != prev_index) { |
225 | if (dev) | 205 | if (dev) |
226 | dev_put(dev); | 206 | dev_put(dev); |
227 | dev = dev_get_by_index(&init_net, pac->acl_ifindex); | 207 | dev = dev_get_by_index(net, pac->acl_ifindex); |
228 | prev_index = pac->acl_ifindex; | 208 | prev_index = pac->acl_ifindex; |
229 | } | 209 | } |
230 | if (dev) | 210 | if (dev) |
@@ -417,14 +397,15 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) | |||
417 | /* | 397 | /* |
418 | * check if given interface (or any, if dev==0) has this anycast address | 398 | * check if given interface (or any, if dev==0) has this anycast address |
419 | */ | 399 | */ |
420 | int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr) | 400 | int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
401 | struct in6_addr *addr) | ||
421 | { | 402 | { |
422 | int found = 0; | 403 | int found = 0; |
423 | 404 | ||
424 | if (dev) | 405 | if (dev) |
425 | return ipv6_chk_acast_dev(dev, addr); | 406 | return ipv6_chk_acast_dev(dev, addr); |
426 | read_lock(&dev_base_lock); | 407 | read_lock(&dev_base_lock); |
427 | for_each_netdev(&init_net, dev) | 408 | for_each_netdev(net, dev) |
428 | if (ipv6_chk_acast_dev(dev, addr)) { | 409 | if (ipv6_chk_acast_dev(dev, addr)) { |
429 | found = 1; | 410 | found = 1; |
430 | break; | 411 | break; |
@@ -436,6 +417,7 @@ int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr) | |||
436 | 417 | ||
437 | #ifdef CONFIG_PROC_FS | 418 | #ifdef CONFIG_PROC_FS |
438 | struct ac6_iter_state { | 419 | struct ac6_iter_state { |
420 | struct seq_net_private p; | ||
439 | struct net_device *dev; | 421 | struct net_device *dev; |
440 | struct inet6_dev *idev; | 422 | struct inet6_dev *idev; |
441 | }; | 423 | }; |
@@ -446,9 +428,10 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) | |||
446 | { | 428 | { |
447 | struct ifacaddr6 *im = NULL; | 429 | struct ifacaddr6 *im = NULL; |
448 | struct ac6_iter_state *state = ac6_seq_private(seq); | 430 | struct ac6_iter_state *state = ac6_seq_private(seq); |
431 | struct net *net = seq_file_net(seq); | ||
449 | 432 | ||
450 | state->idev = NULL; | 433 | state->idev = NULL; |
451 | for_each_netdev(&init_net, state->dev) { | 434 | for_each_netdev(net, state->dev) { |
452 | struct inet6_dev *idev; | 435 | struct inet6_dev *idev; |
453 | idev = in6_dev_get(state->dev); | 436 | idev = in6_dev_get(state->dev); |
454 | if (!idev) | 437 | if (!idev) |
@@ -546,8 +529,8 @@ static const struct seq_operations ac6_seq_ops = { | |||
546 | 529 | ||
547 | static int ac6_seq_open(struct inode *inode, struct file *file) | 530 | static int ac6_seq_open(struct inode *inode, struct file *file) |
548 | { | 531 | { |
549 | return seq_open_private(file, &ac6_seq_ops, | 532 | return seq_open_net(inode, file, &ac6_seq_ops, |
550 | sizeof(struct ac6_iter_state)); | 533 | sizeof(struct ac6_iter_state)); |
551 | } | 534 | } |
552 | 535 | ||
553 | static const struct file_operations ac6_seq_fops = { | 536 | static const struct file_operations ac6_seq_fops = { |
@@ -555,20 +538,20 @@ static const struct file_operations ac6_seq_fops = { | |||
555 | .open = ac6_seq_open, | 538 | .open = ac6_seq_open, |
556 | .read = seq_read, | 539 | .read = seq_read, |
557 | .llseek = seq_lseek, | 540 | .llseek = seq_lseek, |
558 | .release = seq_release_private, | 541 | .release = seq_release_net, |
559 | }; | 542 | }; |
560 | 543 | ||
561 | int __init ac6_proc_init(void) | 544 | int ac6_proc_init(struct net *net) |
562 | { | 545 | { |
563 | if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops)) | 546 | if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops)) |
564 | return -ENOMEM; | 547 | return -ENOMEM; |
565 | 548 | ||
566 | return 0; | 549 | return 0; |
567 | } | 550 | } |
568 | 551 | ||
569 | void ac6_proc_exit(void) | 552 | void ac6_proc_exit(struct net *net) |
570 | { | 553 | { |
571 | proc_net_remove(&init_net, "anycast6"); | 554 | proc_net_remove(net, "anycast6"); |
572 | } | 555 | } |
573 | #endif | 556 | #endif |
574 | 557 | ||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 695c0ca8a417..8d05527524e3 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -29,24 +29,22 @@ struct fib6_rule | |||
29 | u8 tclass; | 29 | u8 tclass; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static struct fib_rules_ops fib6_rules_ops; | 32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
33 | 33 | int flags, pol_lookup_t lookup) | |
34 | struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, | ||
35 | pol_lookup_t lookup) | ||
36 | { | 34 | { |
37 | struct fib_lookup_arg arg = { | 35 | struct fib_lookup_arg arg = { |
38 | .lookup_ptr = lookup, | 36 | .lookup_ptr = lookup, |
39 | }; | 37 | }; |
40 | 38 | ||
41 | fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg); | 39 | fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg); |
42 | if (arg.rule) | 40 | if (arg.rule) |
43 | fib_rule_put(arg.rule); | 41 | fib_rule_put(arg.rule); |
44 | 42 | ||
45 | if (arg.result) | 43 | if (arg.result) |
46 | return arg.result; | 44 | return arg.result; |
47 | 45 | ||
48 | dst_hold(&ip6_null_entry.u.dst); | 46 | dst_hold(&net->ipv6.ip6_null_entry->u.dst); |
49 | return &ip6_null_entry.u.dst; | 47 | return &net->ipv6.ip6_null_entry->u.dst; |
50 | } | 48 | } |
51 | 49 | ||
52 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
@@ -54,28 +52,29 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
54 | { | 52 | { |
55 | struct rt6_info *rt = NULL; | 53 | struct rt6_info *rt = NULL; |
56 | struct fib6_table *table; | 54 | struct fib6_table *table; |
55 | struct net *net = rule->fr_net; | ||
57 | pol_lookup_t lookup = arg->lookup_ptr; | 56 | pol_lookup_t lookup = arg->lookup_ptr; |
58 | 57 | ||
59 | switch (rule->action) { | 58 | switch (rule->action) { |
60 | case FR_ACT_TO_TBL: | 59 | case FR_ACT_TO_TBL: |
61 | break; | 60 | break; |
62 | case FR_ACT_UNREACHABLE: | 61 | case FR_ACT_UNREACHABLE: |
63 | rt = &ip6_null_entry; | 62 | rt = net->ipv6.ip6_null_entry; |
64 | goto discard_pkt; | 63 | goto discard_pkt; |
65 | default: | 64 | default: |
66 | case FR_ACT_BLACKHOLE: | 65 | case FR_ACT_BLACKHOLE: |
67 | rt = &ip6_blk_hole_entry; | 66 | rt = net->ipv6.ip6_blk_hole_entry; |
68 | goto discard_pkt; | 67 | goto discard_pkt; |
69 | case FR_ACT_PROHIBIT: | 68 | case FR_ACT_PROHIBIT: |
70 | rt = &ip6_prohibit_entry; | 69 | rt = net->ipv6.ip6_prohibit_entry; |
71 | goto discard_pkt; | 70 | goto discard_pkt; |
72 | } | 71 | } |
73 | 72 | ||
74 | table = fib6_get_table(rule->table); | 73 | table = fib6_get_table(net, rule->table); |
75 | if (table) | 74 | if (table) |
76 | rt = lookup(table, flp, flags); | 75 | rt = lookup(net, table, flp, flags); |
77 | 76 | ||
78 | if (rt != &ip6_null_entry) { | 77 | if (rt != net->ipv6.ip6_null_entry) { |
79 | struct fib6_rule *r = (struct fib6_rule *)rule; | 78 | struct fib6_rule *r = (struct fib6_rule *)rule; |
80 | 79 | ||
81 | /* | 80 | /* |
@@ -85,8 +84,18 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
85 | if ((rule->flags & FIB_RULE_FIND_SADDR) && | 84 | if ((rule->flags & FIB_RULE_FIND_SADDR) && |
86 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { | 85 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { |
87 | struct in6_addr saddr; | 86 | struct in6_addr saddr; |
88 | if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst, | 87 | unsigned int srcprefs = 0; |
89 | &saddr)) | 88 | |
89 | if (flags & RT6_LOOKUP_F_SRCPREF_TMP) | ||
90 | srcprefs |= IPV6_PREFER_SRC_TMP; | ||
91 | if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC) | ||
92 | srcprefs |= IPV6_PREFER_SRC_PUBLIC; | ||
93 | if (flags & RT6_LOOKUP_F_SRCPREF_COA) | ||
94 | srcprefs |= IPV6_PREFER_SRC_COA; | ||
95 | |||
96 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, | ||
97 | &flp->fl6_dst, srcprefs, | ||
98 | &saddr)) | ||
90 | goto again; | 99 | goto again; |
91 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 100 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
92 | r->src.plen)) | 101 | r->src.plen)) |
@@ -145,13 +154,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
145 | struct nlattr **tb) | 154 | struct nlattr **tb) |
146 | { | 155 | { |
147 | int err = -EINVAL; | 156 | int err = -EINVAL; |
157 | struct net *net = sock_net(skb->sk); | ||
148 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 158 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
149 | 159 | ||
150 | if (rule->action == FR_ACT_TO_TBL) { | 160 | if (rule->action == FR_ACT_TO_TBL) { |
151 | if (rule->table == RT6_TABLE_UNSPEC) | 161 | if (rule->table == RT6_TABLE_UNSPEC) |
152 | goto errout; | 162 | goto errout; |
153 | 163 | ||
154 | if (fib6_new_table(rule->table) == NULL) { | 164 | if (fib6_new_table(net, rule->table) == NULL) { |
155 | err = -ENOBUFS; | 165 | err = -ENOBUFS; |
156 | goto errout; | 166 | goto errout; |
157 | } | 167 | } |
@@ -234,7 +244,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
234 | + nla_total_size(16); /* src */ | 244 | + nla_total_size(16); /* src */ |
235 | } | 245 | } |
236 | 246 | ||
237 | static struct fib_rules_ops fib6_rules_ops = { | 247 | static struct fib_rules_ops fib6_rules_ops_template = { |
238 | .family = AF_INET6, | 248 | .family = AF_INET6, |
239 | .rule_size = sizeof(struct fib6_rule), | 249 | .rule_size = sizeof(struct fib6_rule), |
240 | .addr_size = sizeof(struct in6_addr), | 250 | .addr_size = sizeof(struct in6_addr), |
@@ -247,45 +257,64 @@ static struct fib_rules_ops fib6_rules_ops = { | |||
247 | .nlmsg_payload = fib6_rule_nlmsg_payload, | 257 | .nlmsg_payload = fib6_rule_nlmsg_payload, |
248 | .nlgroup = RTNLGRP_IPV6_RULE, | 258 | .nlgroup = RTNLGRP_IPV6_RULE, |
249 | .policy = fib6_rule_policy, | 259 | .policy = fib6_rule_policy, |
250 | .rules_list = LIST_HEAD_INIT(fib6_rules_ops.rules_list), | ||
251 | .owner = THIS_MODULE, | 260 | .owner = THIS_MODULE, |
252 | .fro_net = &init_net, | 261 | .fro_net = &init_net, |
253 | }; | 262 | }; |
254 | 263 | ||
255 | static int __init fib6_default_rules_init(void) | 264 | static int fib6_rules_net_init(struct net *net) |
256 | { | 265 | { |
257 | int err; | 266 | int err = -ENOMEM; |
258 | 267 | ||
259 | err = fib_default_rule_add(&fib6_rules_ops, 0, | 268 | net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template, |
260 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); | 269 | sizeof(*net->ipv6.fib6_rules_ops), |
261 | if (err < 0) | 270 | GFP_KERNEL); |
262 | return err; | 271 | if (!net->ipv6.fib6_rules_ops) |
263 | err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0); | 272 | goto out; |
264 | if (err < 0) | ||
265 | return err; | ||
266 | return 0; | ||
267 | } | ||
268 | 273 | ||
269 | int __init fib6_rules_init(void) | 274 | net->ipv6.fib6_rules_ops->fro_net = net; |
270 | { | 275 | INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list); |
271 | int ret; | ||
272 | 276 | ||
273 | ret = fib6_default_rules_init(); | 277 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0, |
274 | if (ret) | 278 | RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); |
275 | goto out; | 279 | if (err) |
280 | goto out_fib6_rules_ops; | ||
276 | 281 | ||
277 | ret = fib_rules_register(&fib6_rules_ops); | 282 | err = fib_default_rule_add(net->ipv6.fib6_rules_ops, |
278 | if (ret) | 283 | 0x7FFE, RT6_TABLE_MAIN, 0); |
279 | goto out_default_rules_init; | 284 | if (err) |
285 | goto out_fib6_default_rule_add; | ||
286 | |||
287 | err = fib_rules_register(net->ipv6.fib6_rules_ops); | ||
288 | if (err) | ||
289 | goto out_fib6_default_rule_add; | ||
280 | out: | 290 | out: |
281 | return ret; | 291 | return err; |
282 | 292 | ||
283 | out_default_rules_init: | 293 | out_fib6_default_rule_add: |
284 | fib_rules_cleanup_ops(&fib6_rules_ops); | 294 | fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops); |
295 | out_fib6_rules_ops: | ||
296 | kfree(net->ipv6.fib6_rules_ops); | ||
285 | goto out; | 297 | goto out; |
286 | } | 298 | } |
287 | 299 | ||
300 | static void fib6_rules_net_exit(struct net *net) | ||
301 | { | ||
302 | fib_rules_unregister(net->ipv6.fib6_rules_ops); | ||
303 | kfree(net->ipv6.fib6_rules_ops); | ||
304 | } | ||
305 | |||
306 | static struct pernet_operations fib6_rules_net_ops = { | ||
307 | .init = fib6_rules_net_init, | ||
308 | .exit = fib6_rules_net_exit, | ||
309 | }; | ||
310 | |||
311 | int __init fib6_rules_init(void) | ||
312 | { | ||
313 | return register_pernet_subsys(&fib6_rules_net_ops); | ||
314 | } | ||
315 | |||
316 | |||
288 | void fib6_rules_cleanup(void) | 317 | void fib6_rules_cleanup(void) |
289 | { | 318 | { |
290 | fib_rules_unregister(&fib6_rules_ops); | 319 | unregister_pernet_subsys(&fib6_rules_net_ops); |
291 | } | 320 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 893287ecc628..d42dd16d3487 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <net/addrconf.h> | 64 | #include <net/addrconf.h> |
65 | #include <net/icmp.h> | 65 | #include <net/icmp.h> |
66 | #include <net/xfrm.h> | 66 | #include <net/xfrm.h> |
67 | #include <net/inet_common.h> | ||
67 | 68 | ||
68 | #include <asm/uaccess.h> | 69 | #include <asm/uaccess.h> |
69 | #include <asm/system.h> | 70 | #include <asm/system.h> |
@@ -80,8 +81,10 @@ EXPORT_SYMBOL(icmpv6msg_statistics); | |||
80 | * | 81 | * |
81 | * On SMP we have one ICMP socket per-cpu. | 82 | * On SMP we have one ICMP socket per-cpu. |
82 | */ | 83 | */ |
83 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; | 84 | static inline struct sock *icmpv6_sk(struct net *net) |
84 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) | 85 | { |
86 | return net->ipv6.icmp_sk[smp_processor_id()]; | ||
87 | } | ||
85 | 88 | ||
86 | static int icmpv6_rcv(struct sk_buff *skb); | 89 | static int icmpv6_rcv(struct sk_buff *skb); |
87 | 90 | ||
@@ -90,11 +93,11 @@ static struct inet6_protocol icmpv6_protocol = { | |||
90 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 93 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
91 | }; | 94 | }; |
92 | 95 | ||
93 | static __inline__ int icmpv6_xmit_lock(void) | 96 | static __inline__ int icmpv6_xmit_lock(struct sock *sk) |
94 | { | 97 | { |
95 | local_bh_disable(); | 98 | local_bh_disable(); |
96 | 99 | ||
97 | if (unlikely(!spin_trylock(&icmpv6_socket->sk->sk_lock.slock))) { | 100 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
98 | /* This can happen if the output path (f.e. SIT or | 101 | /* This can happen if the output path (f.e. SIT or |
99 | * ip6ip6 tunnel) signals dst_link_failure() for an | 102 | * ip6ip6 tunnel) signals dst_link_failure() for an |
100 | * outgoing ICMP6 packet. | 103 | * outgoing ICMP6 packet. |
@@ -105,9 +108,9 @@ static __inline__ int icmpv6_xmit_lock(void) | |||
105 | return 0; | 108 | return 0; |
106 | } | 109 | } |
107 | 110 | ||
108 | static __inline__ void icmpv6_xmit_unlock(void) | 111 | static __inline__ void icmpv6_xmit_unlock(struct sock *sk) |
109 | { | 112 | { |
110 | spin_unlock_bh(&icmpv6_socket->sk->sk_lock.slock); | 113 | spin_unlock_bh(&sk->sk_lock.slock); |
111 | } | 114 | } |
112 | 115 | ||
113 | /* | 116 | /* |
@@ -161,6 +164,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
161 | struct flowi *fl) | 164 | struct flowi *fl) |
162 | { | 165 | { |
163 | struct dst_entry *dst; | 166 | struct dst_entry *dst; |
167 | struct net *net = sock_net(sk); | ||
164 | int res = 0; | 168 | int res = 0; |
165 | 169 | ||
166 | /* Informational messages are not limited. */ | 170 | /* Informational messages are not limited. */ |
@@ -176,7 +180,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
176 | * XXX: perhaps the expire for routing entries cloned by | 180 | * XXX: perhaps the expire for routing entries cloned by |
177 | * this lookup should be more aggressive (not longer than timeout). | 181 | * this lookup should be more aggressive (not longer than timeout). |
178 | */ | 182 | */ |
179 | dst = ip6_route_output(sk, fl); | 183 | dst = ip6_route_output(net, sk, fl); |
180 | if (dst->error) { | 184 | if (dst->error) { |
181 | IP6_INC_STATS(ip6_dst_idev(dst), | 185 | IP6_INC_STATS(ip6_dst_idev(dst), |
182 | IPSTATS_MIB_OUTNOROUTES); | 186 | IPSTATS_MIB_OUTNOROUTES); |
@@ -184,7 +188,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
184 | res = 1; | 188 | res = 1; |
185 | } else { | 189 | } else { |
186 | struct rt6_info *rt = (struct rt6_info *)dst; | 190 | struct rt6_info *rt = (struct rt6_info *)dst; |
187 | int tmo = init_net.ipv6.sysctl.icmpv6_time; | 191 | int tmo = net->ipv6.sysctl.icmpv6_time; |
188 | 192 | ||
189 | /* Give more bandwidth to wider prefixes. */ | 193 | /* Give more bandwidth to wider prefixes. */ |
190 | if (rt->rt6i_dst.plen < 128) | 194 | if (rt->rt6i_dst.plen < 128) |
@@ -303,6 +307,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, | 307 | void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, |
304 | struct net_device *dev) | 308 | struct net_device *dev) |
305 | { | 309 | { |
310 | struct net *net = dev_net(skb->dev); | ||
306 | struct inet6_dev *idev = NULL; | 311 | struct inet6_dev *idev = NULL; |
307 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 312 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
308 | struct sock *sk; | 313 | struct sock *sk; |
@@ -332,7 +337,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
332 | */ | 337 | */ |
333 | addr_type = ipv6_addr_type(&hdr->daddr); | 338 | addr_type = ipv6_addr_type(&hdr->daddr); |
334 | 339 | ||
335 | if (ipv6_chk_addr(&init_net, &hdr->daddr, skb->dev, 0)) | 340 | if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0)) |
336 | saddr = &hdr->daddr; | 341 | saddr = &hdr->daddr; |
337 | 342 | ||
338 | /* | 343 | /* |
@@ -389,12 +394,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
389 | fl.fl_icmp_code = code; | 394 | fl.fl_icmp_code = code; |
390 | security_skb_classify_flow(skb, &fl); | 395 | security_skb_classify_flow(skb, &fl); |
391 | 396 | ||
392 | if (icmpv6_xmit_lock()) | 397 | sk = icmpv6_sk(net); |
393 | return; | ||
394 | |||
395 | sk = icmpv6_socket->sk; | ||
396 | np = inet6_sk(sk); | 398 | np = inet6_sk(sk); |
397 | 399 | ||
400 | if (icmpv6_xmit_lock(sk)) | ||
401 | return; | ||
402 | |||
398 | if (!icmpv6_xrlim_allow(sk, type, &fl)) | 403 | if (!icmpv6_xrlim_allow(sk, type, &fl)) |
399 | goto out; | 404 | goto out; |
400 | 405 | ||
@@ -462,9 +467,7 @@ route_done: | |||
462 | else | 467 | else |
463 | hlimit = np->hop_limit; | 468 | hlimit = np->hop_limit; |
464 | if (hlimit < 0) | 469 | if (hlimit < 0) |
465 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 470 | hlimit = ip6_dst_hoplimit(dst); |
466 | if (hlimit < 0) | ||
467 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
468 | 471 | ||
469 | tclass = np->tclass; | 472 | tclass = np->tclass; |
470 | if (tclass < 0) | 473 | if (tclass < 0) |
@@ -500,13 +503,14 @@ out_put: | |||
500 | out_dst_release: | 503 | out_dst_release: |
501 | dst_release(dst); | 504 | dst_release(dst); |
502 | out: | 505 | out: |
503 | icmpv6_xmit_unlock(); | 506 | icmpv6_xmit_unlock(sk); |
504 | } | 507 | } |
505 | 508 | ||
506 | EXPORT_SYMBOL(icmpv6_send); | 509 | EXPORT_SYMBOL(icmpv6_send); |
507 | 510 | ||
508 | static void icmpv6_echo_reply(struct sk_buff *skb) | 511 | static void icmpv6_echo_reply(struct sk_buff *skb) |
509 | { | 512 | { |
513 | struct net *net = dev_net(skb->dev); | ||
510 | struct sock *sk; | 514 | struct sock *sk; |
511 | struct inet6_dev *idev; | 515 | struct inet6_dev *idev; |
512 | struct ipv6_pinfo *np; | 516 | struct ipv6_pinfo *np; |
@@ -537,12 +541,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
537 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 541 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; |
538 | security_skb_classify_flow(skb, &fl); | 542 | security_skb_classify_flow(skb, &fl); |
539 | 543 | ||
540 | if (icmpv6_xmit_lock()) | 544 | sk = icmpv6_sk(net); |
541 | return; | ||
542 | |||
543 | sk = icmpv6_socket->sk; | ||
544 | np = inet6_sk(sk); | 545 | np = inet6_sk(sk); |
545 | 546 | ||
547 | if (icmpv6_xmit_lock(sk)) | ||
548 | return; | ||
549 | |||
546 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 550 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
547 | fl.oif = np->mcast_oif; | 551 | fl.oif = np->mcast_oif; |
548 | 552 | ||
@@ -557,9 +561,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
557 | else | 561 | else |
558 | hlimit = np->hop_limit; | 562 | hlimit = np->hop_limit; |
559 | if (hlimit < 0) | 563 | if (hlimit < 0) |
560 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 564 | hlimit = ip6_dst_hoplimit(dst); |
561 | if (hlimit < 0) | ||
562 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
563 | 565 | ||
564 | tclass = np->tclass; | 566 | tclass = np->tclass; |
565 | if (tclass < 0) | 567 | if (tclass < 0) |
@@ -586,7 +588,7 @@ out_put: | |||
586 | in6_dev_put(idev); | 588 | in6_dev_put(idev); |
587 | dst_release(dst); | 589 | dst_release(dst); |
588 | out: | 590 | out: |
589 | icmpv6_xmit_unlock(); | 591 | icmpv6_xmit_unlock(sk); |
590 | } | 592 | } |
591 | 593 | ||
592 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | 594 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) |
@@ -777,19 +779,40 @@ drop_no_count: | |||
777 | return 0; | 779 | return 0; |
778 | } | 780 | } |
779 | 781 | ||
782 | void icmpv6_flow_init(struct sock *sk, struct flowi *fl, | ||
783 | u8 type, | ||
784 | const struct in6_addr *saddr, | ||
785 | const struct in6_addr *daddr, | ||
786 | int oif) | ||
787 | { | ||
788 | memset(fl, 0, sizeof(*fl)); | ||
789 | ipv6_addr_copy(&fl->fl6_src, saddr); | ||
790 | ipv6_addr_copy(&fl->fl6_dst, daddr); | ||
791 | fl->proto = IPPROTO_ICMPV6; | ||
792 | fl->fl_icmp_type = type; | ||
793 | fl->fl_icmp_code = 0; | ||
794 | fl->oif = oif; | ||
795 | security_sk_classify_flow(sk, fl); | ||
796 | } | ||
797 | |||
780 | /* | 798 | /* |
781 | * Special lock-class for __icmpv6_socket: | 799 | * Special lock-class for __icmpv6_sk: |
782 | */ | 800 | */ |
783 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; | 801 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; |
784 | 802 | ||
785 | int __init icmpv6_init(struct net_proto_family *ops) | 803 | static int __net_init icmpv6_sk_init(struct net *net) |
786 | { | 804 | { |
787 | struct sock *sk; | 805 | struct sock *sk; |
788 | int err, i, j; | 806 | int err, i, j; |
789 | 807 | ||
808 | net->ipv6.icmp_sk = | ||
809 | kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); | ||
810 | if (net->ipv6.icmp_sk == NULL) | ||
811 | return -ENOMEM; | ||
812 | |||
790 | for_each_possible_cpu(i) { | 813 | for_each_possible_cpu(i) { |
791 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, | 814 | err = inet_ctl_sock_create(&sk, PF_INET6, |
792 | &per_cpu(__icmpv6_socket, i)); | 815 | SOCK_RAW, IPPROTO_ICMPV6, net); |
793 | if (err < 0) { | 816 | if (err < 0) { |
794 | printk(KERN_ERR | 817 | printk(KERN_ERR |
795 | "Failed to initialize the ICMP6 control socket " | 818 | "Failed to initialize the ICMP6 control socket " |
@@ -798,12 +821,12 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
798 | goto fail; | 821 | goto fail; |
799 | } | 822 | } |
800 | 823 | ||
801 | sk = per_cpu(__icmpv6_socket, i)->sk; | 824 | net->ipv6.icmp_sk[i] = sk; |
802 | sk->sk_allocation = GFP_ATOMIC; | 825 | |
803 | /* | 826 | /* |
804 | * Split off their lock-class, because sk->sk_dst_lock | 827 | * Split off their lock-class, because sk->sk_dst_lock |
805 | * gets used from softirqs, which is safe for | 828 | * gets used from softirqs, which is safe for |
806 | * __icmpv6_socket (because those never get directly used | 829 | * __icmpv6_sk (because those never get directly used |
807 | * via userspace syscalls), but unsafe for normal sockets. | 830 | * via userspace syscalls), but unsafe for normal sockets. |
808 | */ | 831 | */ |
809 | lockdep_set_class(&sk->sk_dst_lock, | 832 | lockdep_set_class(&sk->sk_dst_lock, |
@@ -814,39 +837,57 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
814 | */ | 837 | */ |
815 | sk->sk_sndbuf = | 838 | sk->sk_sndbuf = |
816 | (2 * ((64 * 1024) + sizeof(struct sk_buff))); | 839 | (2 * ((64 * 1024) + sizeof(struct sk_buff))); |
817 | |||
818 | sk->sk_prot->unhash(sk); | ||
819 | } | 840 | } |
820 | |||
821 | |||
822 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) { | ||
823 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
824 | err = -EAGAIN; | ||
825 | goto fail; | ||
826 | } | ||
827 | |||
828 | return 0; | 841 | return 0; |
829 | 842 | ||
830 | fail: | 843 | fail: |
831 | for (j = 0; j < i; j++) { | 844 | for (j = 0; j < i; j++) |
832 | if (!cpu_possible(j)) | 845 | inet_ctl_sock_destroy(net->ipv6.icmp_sk[j]); |
833 | continue; | 846 | kfree(net->ipv6.icmp_sk); |
834 | sock_release(per_cpu(__icmpv6_socket, j)); | ||
835 | } | ||
836 | |||
837 | return err; | 847 | return err; |
838 | } | 848 | } |
839 | 849 | ||
840 | void icmpv6_cleanup(void) | 850 | static void __net_exit icmpv6_sk_exit(struct net *net) |
841 | { | 851 | { |
842 | int i; | 852 | int i; |
843 | 853 | ||
844 | for_each_possible_cpu(i) { | 854 | for_each_possible_cpu(i) { |
845 | sock_release(per_cpu(__icmpv6_socket, i)); | 855 | inet_ctl_sock_destroy(net->ipv6.icmp_sk[i]); |
846 | } | 856 | } |
857 | kfree(net->ipv6.icmp_sk); | ||
858 | } | ||
859 | |||
860 | static struct pernet_operations icmpv6_sk_ops = { | ||
861 | .init = icmpv6_sk_init, | ||
862 | .exit = icmpv6_sk_exit, | ||
863 | }; | ||
864 | |||
865 | int __init icmpv6_init(void) | ||
866 | { | ||
867 | int err; | ||
868 | |||
869 | err = register_pernet_subsys(&icmpv6_sk_ops); | ||
870 | if (err < 0) | ||
871 | return err; | ||
872 | |||
873 | err = -EAGAIN; | ||
874 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) | ||
875 | goto fail; | ||
876 | return 0; | ||
877 | |||
878 | fail: | ||
879 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
880 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
881 | return err; | ||
882 | } | ||
883 | |||
884 | void icmpv6_cleanup(void) | ||
885 | { | ||
886 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
847 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | 887 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); |
848 | } | 888 | } |
849 | 889 | ||
890 | |||
850 | static const struct icmp6_err { | 891 | static const struct icmp6_err { |
851 | int err; | 892 | int err; |
852 | int fatal; | 893 | int fatal; |
@@ -927,6 +968,10 @@ struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) | |||
927 | table = kmemdup(ipv6_icmp_table_template, | 968 | table = kmemdup(ipv6_icmp_table_template, |
928 | sizeof(ipv6_icmp_table_template), | 969 | sizeof(ipv6_icmp_table_template), |
929 | GFP_KERNEL); | 970 | GFP_KERNEL); |
971 | |||
972 | if (table) | ||
973 | table[0].data = &net->ipv6.sysctl.icmpv6_time; | ||
974 | |||
930 | return table; | 975 | return table; |
931 | } | 976 | } |
932 | #endif | 977 | #endif |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 99fd25f7f005..580014aea4d6 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 | ||
@@ -43,7 +43,7 @@ void __inet6_hash(struct sock *sk) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | __sk_add_node(sk, list); | 45 | __sk_add_node(sk, list); |
46 | sock_prot_inuse_add(sk->sk_prot, 1); | 46 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
47 | write_unlock(lock); | 47 | write_unlock(lock); |
48 | } | 48 | } |
49 | EXPORT_SYMBOL(__inet6_hash); | 49 | EXPORT_SYMBOL(__inet6_hash); |
@@ -105,7 +105,7 @@ struct sock *inet6_lookup_listener(struct net *net, | |||
105 | 105 | ||
106 | read_lock(&hashinfo->lhash_lock); | 106 | read_lock(&hashinfo->lhash_lock); |
107 | sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { | 107 | sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { |
108 | if (sk->sk_net == net && inet_sk(sk)->num == hnum && | 108 | if (net_eq(sock_net(sk), net) && inet_sk(sk)->num == hnum && |
109 | sk->sk_family == PF_INET6) { | 109 | sk->sk_family == PF_INET6) { |
110 | const struct ipv6_pinfo *np = inet6_sk(sk); | 110 | const struct ipv6_pinfo *np = inet6_sk(sk); |
111 | 111 | ||
@@ -172,7 +172,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, | |||
172 | struct sock *sk2; | 172 | struct sock *sk2; |
173 | const struct hlist_node *node; | 173 | const struct hlist_node *node; |
174 | struct inet_timewait_sock *tw; | 174 | struct inet_timewait_sock *tw; |
175 | struct net *net = sk->sk_net; | 175 | struct net *net = sock_net(sk); |
176 | 176 | ||
177 | prefetch(head->chain.first); | 177 | prefetch(head->chain.first); |
178 | write_lock(lock); | 178 | write_lock(lock); |
@@ -204,7 +204,7 @@ unique: | |||
204 | BUG_TRAP(sk_unhashed(sk)); | 204 | BUG_TRAP(sk_unhashed(sk)); |
205 | __sk_add_node(sk, &head->chain); | 205 | __sk_add_node(sk, &head->chain); |
206 | sk->sk_hash = hash; | 206 | sk->sk_hash = hash; |
207 | sock_prot_inuse_add(sk->sk_prot, 1); | 207 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
208 | write_unlock(lock); | 208 | write_unlock(lock); |
209 | 209 | ||
210 | if (twp != NULL) { | 210 | if (twp != NULL) { |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index bab72b6f1444..b3f6e03c454c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -48,8 +48,6 @@ | |||
48 | #define RT6_TRACE(x...) do { ; } while (0) | 48 | #define RT6_TRACE(x...) do { ; } while (0) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | struct rt6_statistics rt6_stats; | ||
52 | |||
53 | static struct kmem_cache * fib6_node_kmem __read_mostly; | 51 | static struct kmem_cache * fib6_node_kmem __read_mostly; |
54 | 52 | ||
55 | enum fib_walk_state_t | 53 | enum fib_walk_state_t |
@@ -66,6 +64,7 @@ enum fib_walk_state_t | |||
66 | struct fib6_cleaner_t | 64 | struct fib6_cleaner_t |
67 | { | 65 | { |
68 | struct fib6_walker_t w; | 66 | struct fib6_walker_t w; |
67 | struct net *net; | ||
69 | int (*func)(struct rt6_info *, void *arg); | 68 | int (*func)(struct rt6_info *, void *arg); |
70 | void *arg; | 69 | void *arg; |
71 | }; | 70 | }; |
@@ -78,9 +77,10 @@ static DEFINE_RWLOCK(fib6_walker_lock); | |||
78 | #define FWS_INIT FWS_L | 77 | #define FWS_INIT FWS_L |
79 | #endif | 78 | #endif |
80 | 79 | ||
81 | static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt); | 80 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, |
82 | static struct rt6_info * fib6_find_prefix(struct fib6_node *fn); | 81 | struct rt6_info *rt); |
83 | static struct fib6_node * fib6_repair_tree(struct fib6_node *fn); | 82 | static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn); |
83 | static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn); | ||
84 | static int fib6_walk(struct fib6_walker_t *w); | 84 | static int fib6_walk(struct fib6_walker_t *w); |
85 | static int fib6_walk_continue(struct fib6_walker_t *w); | 85 | static int fib6_walk_continue(struct fib6_walker_t *w); |
86 | 86 | ||
@@ -93,7 +93,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w); | |||
93 | 93 | ||
94 | static __u32 rt_sernum; | 94 | static __u32 rt_sernum; |
95 | 95 | ||
96 | static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0); | 96 | static void fib6_gc_timer_cb(unsigned long arg); |
97 | 97 | ||
98 | static struct fib6_walker_t fib6_walker_list = { | 98 | static struct fib6_walker_t fib6_walker_list = { |
99 | .prev = &fib6_walker_list, | 99 | .prev = &fib6_walker_list, |
@@ -166,22 +166,13 @@ static __inline__ void rt6_release(struct rt6_info *rt) | |||
166 | dst_free(&rt->u.dst); | 166 | dst_free(&rt->u.dst); |
167 | } | 167 | } |
168 | 168 | ||
169 | static struct fib6_table fib6_main_tbl = { | ||
170 | .tb6_id = RT6_TABLE_MAIN, | ||
171 | .tb6_root = { | ||
172 | .leaf = &ip6_null_entry, | ||
173 | .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 169 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
178 | #define FIB_TABLE_HASHSZ 256 | 170 | #define FIB_TABLE_HASHSZ 256 |
179 | #else | 171 | #else |
180 | #define FIB_TABLE_HASHSZ 1 | 172 | #define FIB_TABLE_HASHSZ 1 |
181 | #endif | 173 | #endif |
182 | static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; | ||
183 | 174 | ||
184 | static void fib6_link_table(struct fib6_table *tb) | 175 | static void fib6_link_table(struct net *net, struct fib6_table *tb) |
185 | { | 176 | { |
186 | unsigned int h; | 177 | unsigned int h; |
187 | 178 | ||
@@ -197,52 +188,46 @@ static void fib6_link_table(struct fib6_table *tb) | |||
197 | * No protection necessary, this is the only list mutatation | 188 | * No protection necessary, this is the only list mutatation |
198 | * operation, tables never disappear once they exist. | 189 | * operation, tables never disappear once they exist. |
199 | */ | 190 | */ |
200 | hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]); | 191 | hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]); |
201 | } | 192 | } |
202 | 193 | ||
203 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 194 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
204 | static struct fib6_table fib6_local_tbl = { | ||
205 | .tb6_id = RT6_TABLE_LOCAL, | ||
206 | .tb6_root = { | ||
207 | .leaf = &ip6_null_entry, | ||
208 | .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, | ||
209 | }, | ||
210 | }; | ||
211 | 195 | ||
212 | static struct fib6_table *fib6_alloc_table(u32 id) | 196 | static struct fib6_table *fib6_alloc_table(struct net *net, u32 id) |
213 | { | 197 | { |
214 | struct fib6_table *table; | 198 | struct fib6_table *table; |
215 | 199 | ||
216 | table = kzalloc(sizeof(*table), GFP_ATOMIC); | 200 | table = kzalloc(sizeof(*table), GFP_ATOMIC); |
217 | if (table != NULL) { | 201 | if (table != NULL) { |
218 | table->tb6_id = id; | 202 | table->tb6_id = id; |
219 | table->tb6_root.leaf = &ip6_null_entry; | 203 | table->tb6_root.leaf = net->ipv6.ip6_null_entry; |
220 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | 204 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
221 | } | 205 | } |
222 | 206 | ||
223 | return table; | 207 | return table; |
224 | } | 208 | } |
225 | 209 | ||
226 | struct fib6_table *fib6_new_table(u32 id) | 210 | struct fib6_table *fib6_new_table(struct net *net, u32 id) |
227 | { | 211 | { |
228 | struct fib6_table *tb; | 212 | struct fib6_table *tb; |
229 | 213 | ||
230 | if (id == 0) | 214 | if (id == 0) |
231 | id = RT6_TABLE_MAIN; | 215 | id = RT6_TABLE_MAIN; |
232 | tb = fib6_get_table(id); | 216 | tb = fib6_get_table(net, id); |
233 | if (tb) | 217 | if (tb) |
234 | return tb; | 218 | return tb; |
235 | 219 | ||
236 | tb = fib6_alloc_table(id); | 220 | tb = fib6_alloc_table(net, id); |
237 | if (tb != NULL) | 221 | if (tb != NULL) |
238 | fib6_link_table(tb); | 222 | fib6_link_table(net, tb); |
239 | 223 | ||
240 | return tb; | 224 | return tb; |
241 | } | 225 | } |
242 | 226 | ||
243 | struct fib6_table *fib6_get_table(u32 id) | 227 | struct fib6_table *fib6_get_table(struct net *net, u32 id) |
244 | { | 228 | { |
245 | struct fib6_table *tb; | 229 | struct fib6_table *tb; |
230 | struct hlist_head *head; | ||
246 | struct hlist_node *node; | 231 | struct hlist_node *node; |
247 | unsigned int h; | 232 | unsigned int h; |
248 | 233 | ||
@@ -250,7 +235,8 @@ struct fib6_table *fib6_get_table(u32 id) | |||
250 | id = RT6_TABLE_MAIN; | 235 | id = RT6_TABLE_MAIN; |
251 | h = id & (FIB_TABLE_HASHSZ - 1); | 236 | h = id & (FIB_TABLE_HASHSZ - 1); |
252 | rcu_read_lock(); | 237 | rcu_read_lock(); |
253 | hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) { | 238 | head = &net->ipv6.fib_table_hash[h]; |
239 | hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) { | ||
254 | if (tb->tb6_id == id) { | 240 | if (tb->tb6_id == id) { |
255 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
256 | return tb; | 242 | return tb; |
@@ -261,33 +247,32 @@ struct fib6_table *fib6_get_table(u32 id) | |||
261 | return NULL; | 247 | return NULL; |
262 | } | 248 | } |
263 | 249 | ||
264 | static void __init fib6_tables_init(void) | 250 | static void fib6_tables_init(struct net *net) |
265 | { | 251 | { |
266 | fib6_link_table(&fib6_main_tbl); | 252 | fib6_link_table(net, net->ipv6.fib6_main_tbl); |
267 | fib6_link_table(&fib6_local_tbl); | 253 | fib6_link_table(net, net->ipv6.fib6_local_tbl); |
268 | } | 254 | } |
269 | |||
270 | #else | 255 | #else |
271 | 256 | ||
272 | struct fib6_table *fib6_new_table(u32 id) | 257 | struct fib6_table *fib6_new_table(struct net *net, u32 id) |
273 | { | 258 | { |
274 | return fib6_get_table(id); | 259 | return fib6_get_table(net, id); |
275 | } | 260 | } |
276 | 261 | ||
277 | struct fib6_table *fib6_get_table(u32 id) | 262 | struct fib6_table *fib6_get_table(struct net *net, u32 id) |
278 | { | 263 | { |
279 | return &fib6_main_tbl; | 264 | return net->ipv6.fib6_main_tbl; |
280 | } | 265 | } |
281 | 266 | ||
282 | struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, | 267 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
283 | pol_lookup_t lookup) | 268 | int flags, pol_lookup_t lookup) |
284 | { | 269 | { |
285 | return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags); | 270 | return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags); |
286 | } | 271 | } |
287 | 272 | ||
288 | static void __init fib6_tables_init(void) | 273 | static void fib6_tables_init(struct net *net) |
289 | { | 274 | { |
290 | fib6_link_table(&fib6_main_tbl); | 275 | fib6_link_table(net, net->ipv6.fib6_main_tbl); |
291 | } | 276 | } |
292 | 277 | ||
293 | #endif | 278 | #endif |
@@ -361,18 +346,16 @@ end: | |||
361 | 346 | ||
362 | static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | 347 | static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) |
363 | { | 348 | { |
364 | struct net *net = skb->sk->sk_net; | 349 | struct net *net = sock_net(skb->sk); |
365 | unsigned int h, s_h; | 350 | unsigned int h, s_h; |
366 | unsigned int e = 0, s_e; | 351 | unsigned int e = 0, s_e; |
367 | struct rt6_rtnl_dump_arg arg; | 352 | struct rt6_rtnl_dump_arg arg; |
368 | struct fib6_walker_t *w; | 353 | struct fib6_walker_t *w; |
369 | struct fib6_table *tb; | 354 | struct fib6_table *tb; |
370 | struct hlist_node *node; | 355 | struct hlist_node *node; |
356 | struct hlist_head *head; | ||
371 | int res = 0; | 357 | int res = 0; |
372 | 358 | ||
373 | if (net != &init_net) | ||
374 | return 0; | ||
375 | |||
376 | s_h = cb->args[0]; | 359 | s_h = cb->args[0]; |
377 | s_e = cb->args[1]; | 360 | s_e = cb->args[1]; |
378 | 361 | ||
@@ -401,7 +384,8 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
401 | 384 | ||
402 | for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { | 385 | for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { |
403 | e = 0; | 386 | e = 0; |
404 | hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) { | 387 | head = &net->ipv6.fib_table_hash[h]; |
388 | hlist_for_each_entry(tb, node, head, tb6_hlist) { | ||
405 | if (e < s_e) | 389 | if (e < s_e) |
406 | goto next; | 390 | goto next; |
407 | res = fib6_dump_table(tb, skb, cb); | 391 | res = fib6_dump_table(tb, skb, cb); |
@@ -667,29 +651,29 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
667 | rt->rt6i_node = fn; | 651 | rt->rt6i_node = fn; |
668 | atomic_inc(&rt->rt6i_ref); | 652 | atomic_inc(&rt->rt6i_ref); |
669 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | 653 | inet6_rt_notify(RTM_NEWROUTE, rt, info); |
670 | rt6_stats.fib_rt_entries++; | 654 | info->nl_net->ipv6.rt6_stats->fib_rt_entries++; |
671 | 655 | ||
672 | if ((fn->fn_flags & RTN_RTINFO) == 0) { | 656 | if ((fn->fn_flags & RTN_RTINFO) == 0) { |
673 | rt6_stats.fib_route_nodes++; | 657 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
674 | fn->fn_flags |= RTN_RTINFO; | 658 | fn->fn_flags |= RTN_RTINFO; |
675 | } | 659 | } |
676 | 660 | ||
677 | return 0; | 661 | return 0; |
678 | } | 662 | } |
679 | 663 | ||
680 | static __inline__ void fib6_start_gc(struct rt6_info *rt) | 664 | static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt) |
681 | { | 665 | { |
682 | if (ip6_fib_timer.expires == 0 && | 666 | if (net->ipv6.ip6_fib_timer->expires == 0 && |
683 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) | 667 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) |
684 | mod_timer(&ip6_fib_timer, jiffies + | 668 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
685 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 669 | net->ipv6.sysctl.ip6_rt_gc_interval); |
686 | } | 670 | } |
687 | 671 | ||
688 | void fib6_force_start_gc(void) | 672 | void fib6_force_start_gc(struct net *net) |
689 | { | 673 | { |
690 | if (ip6_fib_timer.expires == 0) | 674 | if (net->ipv6.ip6_fib_timer->expires == 0) |
691 | mod_timer(&ip6_fib_timer, jiffies + | 675 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
692 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 676 | net->ipv6.sysctl.ip6_rt_gc_interval); |
693 | } | 677 | } |
694 | 678 | ||
695 | /* | 679 | /* |
@@ -733,8 +717,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
733 | if (sfn == NULL) | 717 | if (sfn == NULL) |
734 | goto st_failure; | 718 | goto st_failure; |
735 | 719 | ||
736 | sfn->leaf = &ip6_null_entry; | 720 | sfn->leaf = info->nl_net->ipv6.ip6_null_entry; |
737 | atomic_inc(&ip6_null_entry.rt6i_ref); | 721 | atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); |
738 | sfn->fn_flags = RTN_ROOT; | 722 | sfn->fn_flags = RTN_ROOT; |
739 | sfn->fn_sernum = fib6_new_sernum(); | 723 | sfn->fn_sernum = fib6_new_sernum(); |
740 | 724 | ||
@@ -776,9 +760,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
776 | err = fib6_add_rt2node(fn, rt, info); | 760 | err = fib6_add_rt2node(fn, rt, info); |
777 | 761 | ||
778 | if (err == 0) { | 762 | if (err == 0) { |
779 | fib6_start_gc(rt); | 763 | fib6_start_gc(info->nl_net, rt); |
780 | if (!(rt->rt6i_flags&RTF_CACHE)) | 764 | if (!(rt->rt6i_flags&RTF_CACHE)) |
781 | fib6_prune_clones(pn, rt); | 765 | fib6_prune_clones(info->nl_net, pn, rt); |
782 | } | 766 | } |
783 | 767 | ||
784 | out: | 768 | out: |
@@ -789,11 +773,11 @@ out: | |||
789 | * super-tree leaf node we have to find a new one for it. | 773 | * super-tree leaf node we have to find a new one for it. |
790 | */ | 774 | */ |
791 | if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { | 775 | if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { |
792 | pn->leaf = fib6_find_prefix(pn); | 776 | pn->leaf = fib6_find_prefix(info->nl_net, pn); |
793 | #if RT6_DEBUG >= 2 | 777 | #if RT6_DEBUG >= 2 |
794 | if (!pn->leaf) { | 778 | if (!pn->leaf) { |
795 | BUG_TRAP(pn->leaf != NULL); | 779 | BUG_TRAP(pn->leaf != NULL); |
796 | pn->leaf = &ip6_null_entry; | 780 | pn->leaf = info->nl_net->ipv6.ip6_null_entry; |
797 | } | 781 | } |
798 | #endif | 782 | #endif |
799 | atomic_inc(&pn->leaf->rt6i_ref); | 783 | atomic_inc(&pn->leaf->rt6i_ref); |
@@ -809,7 +793,7 @@ out: | |||
809 | */ | 793 | */ |
810 | st_failure: | 794 | st_failure: |
811 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) | 795 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) |
812 | fib6_repair_tree(fn); | 796 | fib6_repair_tree(info->nl_net, fn); |
813 | dst_free(&rt->u.dst); | 797 | dst_free(&rt->u.dst); |
814 | return err; | 798 | return err; |
815 | #endif | 799 | #endif |
@@ -975,10 +959,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root, | |||
975 | * | 959 | * |
976 | */ | 960 | */ |
977 | 961 | ||
978 | static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | 962 | static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn) |
979 | { | 963 | { |
980 | if (fn->fn_flags&RTN_ROOT) | 964 | if (fn->fn_flags&RTN_ROOT) |
981 | return &ip6_null_entry; | 965 | return net->ipv6.ip6_null_entry; |
982 | 966 | ||
983 | while(fn) { | 967 | while(fn) { |
984 | if(fn->left) | 968 | if(fn->left) |
@@ -997,7 +981,8 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | |||
997 | * is the node we want to try and remove. | 981 | * is the node we want to try and remove. |
998 | */ | 982 | */ |
999 | 983 | ||
1000 | static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) | 984 | static struct fib6_node *fib6_repair_tree(struct net *net, |
985 | struct fib6_node *fn) | ||
1001 | { | 986 | { |
1002 | int children; | 987 | int children; |
1003 | int nstate; | 988 | int nstate; |
@@ -1024,11 +1009,11 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) | |||
1024 | || (children && fn->fn_flags&RTN_ROOT) | 1009 | || (children && fn->fn_flags&RTN_ROOT) |
1025 | #endif | 1010 | #endif |
1026 | ) { | 1011 | ) { |
1027 | fn->leaf = fib6_find_prefix(fn); | 1012 | fn->leaf = fib6_find_prefix(net, fn); |
1028 | #if RT6_DEBUG >= 2 | 1013 | #if RT6_DEBUG >= 2 |
1029 | if (fn->leaf==NULL) { | 1014 | if (fn->leaf==NULL) { |
1030 | BUG_TRAP(fn->leaf); | 1015 | BUG_TRAP(fn->leaf); |
1031 | fn->leaf = &ip6_null_entry; | 1016 | fn->leaf = net->ipv6.ip6_null_entry; |
1032 | } | 1017 | } |
1033 | #endif | 1018 | #endif |
1034 | atomic_inc(&fn->leaf->rt6i_ref); | 1019 | atomic_inc(&fn->leaf->rt6i_ref); |
@@ -1101,14 +1086,15 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1101 | { | 1086 | { |
1102 | struct fib6_walker_t *w; | 1087 | struct fib6_walker_t *w; |
1103 | struct rt6_info *rt = *rtp; | 1088 | struct rt6_info *rt = *rtp; |
1089 | struct net *net = info->nl_net; | ||
1104 | 1090 | ||
1105 | RT6_TRACE("fib6_del_route\n"); | 1091 | RT6_TRACE("fib6_del_route\n"); |
1106 | 1092 | ||
1107 | /* Unlink it */ | 1093 | /* Unlink it */ |
1108 | *rtp = rt->u.dst.rt6_next; | 1094 | *rtp = rt->u.dst.rt6_next; |
1109 | rt->rt6i_node = NULL; | 1095 | rt->rt6i_node = NULL; |
1110 | rt6_stats.fib_rt_entries--; | 1096 | net->ipv6.rt6_stats->fib_rt_entries--; |
1111 | rt6_stats.fib_discarded_routes++; | 1097 | net->ipv6.rt6_stats->fib_discarded_routes++; |
1112 | 1098 | ||
1113 | /* Reset round-robin state, if necessary */ | 1099 | /* Reset round-robin state, if necessary */ |
1114 | if (fn->rr_ptr == rt) | 1100 | if (fn->rr_ptr == rt) |
@@ -1131,8 +1117,8 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1131 | /* If it was last route, expunge its radix tree node */ | 1117 | /* If it was last route, expunge its radix tree node */ |
1132 | if (fn->leaf == NULL) { | 1118 | if (fn->leaf == NULL) { |
1133 | fn->fn_flags &= ~RTN_RTINFO; | 1119 | fn->fn_flags &= ~RTN_RTINFO; |
1134 | rt6_stats.fib_route_nodes--; | 1120 | net->ipv6.rt6_stats->fib_route_nodes--; |
1135 | fn = fib6_repair_tree(fn); | 1121 | fn = fib6_repair_tree(net, fn); |
1136 | } | 1122 | } |
1137 | 1123 | ||
1138 | if (atomic_read(&rt->rt6i_ref) != 1) { | 1124 | if (atomic_read(&rt->rt6i_ref) != 1) { |
@@ -1144,7 +1130,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1144 | */ | 1130 | */ |
1145 | while (fn) { | 1131 | while (fn) { |
1146 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { | 1132 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { |
1147 | fn->leaf = fib6_find_prefix(fn); | 1133 | fn->leaf = fib6_find_prefix(net, fn); |
1148 | atomic_inc(&fn->leaf->rt6i_ref); | 1134 | atomic_inc(&fn->leaf->rt6i_ref); |
1149 | rt6_release(rt); | 1135 | rt6_release(rt); |
1150 | } | 1136 | } |
@@ -1160,6 +1146,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1160 | 1146 | ||
1161 | int fib6_del(struct rt6_info *rt, struct nl_info *info) | 1147 | int fib6_del(struct rt6_info *rt, struct nl_info *info) |
1162 | { | 1148 | { |
1149 | struct net *net = info->nl_net; | ||
1163 | struct fib6_node *fn = rt->rt6i_node; | 1150 | struct fib6_node *fn = rt->rt6i_node; |
1164 | struct rt6_info **rtp; | 1151 | struct rt6_info **rtp; |
1165 | 1152 | ||
@@ -1169,7 +1156,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1169 | return -ENOENT; | 1156 | return -ENOENT; |
1170 | } | 1157 | } |
1171 | #endif | 1158 | #endif |
1172 | if (fn == NULL || rt == &ip6_null_entry) | 1159 | if (fn == NULL || rt == net->ipv6.ip6_null_entry) |
1173 | return -ENOENT; | 1160 | return -ENOENT; |
1174 | 1161 | ||
1175 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); | 1162 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); |
@@ -1184,7 +1171,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1184 | pn = pn->parent; | 1171 | pn = pn->parent; |
1185 | } | 1172 | } |
1186 | #endif | 1173 | #endif |
1187 | fib6_prune_clones(pn, rt); | 1174 | fib6_prune_clones(info->nl_net, pn, rt); |
1188 | } | 1175 | } |
1189 | 1176 | ||
1190 | /* | 1177 | /* |
@@ -1314,12 +1301,12 @@ static int fib6_walk(struct fib6_walker_t *w) | |||
1314 | 1301 | ||
1315 | static int fib6_clean_node(struct fib6_walker_t *w) | 1302 | static int fib6_clean_node(struct fib6_walker_t *w) |
1316 | { | 1303 | { |
1317 | struct nl_info info = { | ||
1318 | .nl_net = &init_net, | ||
1319 | }; | ||
1320 | int res; | 1304 | int res; |
1321 | struct rt6_info *rt; | 1305 | struct rt6_info *rt; |
1322 | struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w); | 1306 | struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w); |
1307 | struct nl_info info = { | ||
1308 | .nl_net = c->net, | ||
1309 | }; | ||
1323 | 1310 | ||
1324 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { | 1311 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { |
1325 | res = c->func(rt, c->arg); | 1312 | res = c->func(rt, c->arg); |
@@ -1351,7 +1338,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) | |||
1351 | * ignoring pure split nodes) will be scanned. | 1338 | * ignoring pure split nodes) will be scanned. |
1352 | */ | 1339 | */ |
1353 | 1340 | ||
1354 | static void fib6_clean_tree(struct fib6_node *root, | 1341 | static void fib6_clean_tree(struct net *net, struct fib6_node *root, |
1355 | int (*func)(struct rt6_info *, void *arg), | 1342 | int (*func)(struct rt6_info *, void *arg), |
1356 | int prune, void *arg) | 1343 | int prune, void *arg) |
1357 | { | 1344 | { |
@@ -1362,23 +1349,26 @@ static void fib6_clean_tree(struct fib6_node *root, | |||
1362 | c.w.prune = prune; | 1349 | c.w.prune = prune; |
1363 | c.func = func; | 1350 | c.func = func; |
1364 | c.arg = arg; | 1351 | c.arg = arg; |
1352 | c.net = net; | ||
1365 | 1353 | ||
1366 | fib6_walk(&c.w); | 1354 | fib6_walk(&c.w); |
1367 | } | 1355 | } |
1368 | 1356 | ||
1369 | void fib6_clean_all(int (*func)(struct rt6_info *, void *arg), | 1357 | void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), |
1370 | int prune, void *arg) | 1358 | int prune, void *arg) |
1371 | { | 1359 | { |
1372 | struct fib6_table *table; | 1360 | struct fib6_table *table; |
1373 | struct hlist_node *node; | 1361 | struct hlist_node *node; |
1362 | struct hlist_head *head; | ||
1374 | unsigned int h; | 1363 | unsigned int h; |
1375 | 1364 | ||
1376 | rcu_read_lock(); | 1365 | rcu_read_lock(); |
1377 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { | 1366 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { |
1378 | hlist_for_each_entry_rcu(table, node, &fib_table_hash[h], | 1367 | head = &net->ipv6.fib_table_hash[h]; |
1379 | tb6_hlist) { | 1368 | hlist_for_each_entry_rcu(table, node, head, tb6_hlist) { |
1380 | write_lock_bh(&table->tb6_lock); | 1369 | write_lock_bh(&table->tb6_lock); |
1381 | fib6_clean_tree(&table->tb6_root, func, prune, arg); | 1370 | fib6_clean_tree(net, &table->tb6_root, |
1371 | func, prune, arg); | ||
1382 | write_unlock_bh(&table->tb6_lock); | 1372 | write_unlock_bh(&table->tb6_lock); |
1383 | } | 1373 | } |
1384 | } | 1374 | } |
@@ -1395,9 +1385,10 @@ static int fib6_prune_clone(struct rt6_info *rt, void *arg) | |||
1395 | return 0; | 1385 | return 0; |
1396 | } | 1386 | } |
1397 | 1387 | ||
1398 | static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt) | 1388 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, |
1389 | struct rt6_info *rt) | ||
1399 | { | 1390 | { |
1400 | fib6_clean_tree(fn, fib6_prune_clone, 1, rt); | 1391 | fib6_clean_tree(net, fn, fib6_prune_clone, 1, rt); |
1401 | } | 1392 | } |
1402 | 1393 | ||
1403 | /* | 1394 | /* |
@@ -1447,54 +1438,145 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1447 | 1438 | ||
1448 | static DEFINE_SPINLOCK(fib6_gc_lock); | 1439 | static DEFINE_SPINLOCK(fib6_gc_lock); |
1449 | 1440 | ||
1450 | void fib6_run_gc(unsigned long dummy) | 1441 | void fib6_run_gc(unsigned long expires, struct net *net) |
1451 | { | 1442 | { |
1452 | if (dummy != ~0UL) { | 1443 | if (expires != ~0UL) { |
1453 | spin_lock_bh(&fib6_gc_lock); | 1444 | spin_lock_bh(&fib6_gc_lock); |
1454 | gc_args.timeout = dummy ? (int)dummy : | 1445 | gc_args.timeout = expires ? (int)expires : |
1455 | init_net.ipv6.sysctl.ip6_rt_gc_interval; | 1446 | net->ipv6.sysctl.ip6_rt_gc_interval; |
1456 | } else { | 1447 | } else { |
1457 | local_bh_disable(); | 1448 | local_bh_disable(); |
1458 | if (!spin_trylock(&fib6_gc_lock)) { | 1449 | if (!spin_trylock(&fib6_gc_lock)) { |
1459 | mod_timer(&ip6_fib_timer, jiffies + HZ); | 1450 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ); |
1460 | local_bh_enable(); | 1451 | local_bh_enable(); |
1461 | return; | 1452 | return; |
1462 | } | 1453 | } |
1463 | gc_args.timeout = init_net.ipv6.sysctl.ip6_rt_gc_interval; | 1454 | gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval; |
1464 | } | 1455 | } |
1465 | gc_args.more = 0; | 1456 | gc_args.more = 0; |
1466 | 1457 | ||
1467 | ndisc_dst_gc(&gc_args.more); | 1458 | icmp6_dst_gc(&gc_args.more); |
1468 | fib6_clean_all(fib6_age, 0, NULL); | 1459 | |
1460 | fib6_clean_all(net, fib6_age, 0, NULL); | ||
1469 | 1461 | ||
1470 | if (gc_args.more) | 1462 | if (gc_args.more) |
1471 | mod_timer(&ip6_fib_timer, jiffies + | 1463 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
1472 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 1464 | net->ipv6.sysctl.ip6_rt_gc_interval); |
1473 | else { | 1465 | else { |
1474 | del_timer(&ip6_fib_timer); | 1466 | del_timer(net->ipv6.ip6_fib_timer); |
1475 | ip6_fib_timer.expires = 0; | 1467 | net->ipv6.ip6_fib_timer->expires = 0; |
1476 | } | 1468 | } |
1477 | spin_unlock_bh(&fib6_gc_lock); | 1469 | spin_unlock_bh(&fib6_gc_lock); |
1478 | } | 1470 | } |
1479 | 1471 | ||
1480 | int __init fib6_init(void) | 1472 | static void fib6_gc_timer_cb(unsigned long arg) |
1473 | { | ||
1474 | fib6_run_gc(0, (struct net *)arg); | ||
1475 | } | ||
1476 | |||
1477 | static int fib6_net_init(struct net *net) | ||
1481 | { | 1478 | { |
1482 | int ret; | 1479 | int ret; |
1480 | struct timer_list *timer; | ||
1481 | |||
1482 | ret = -ENOMEM; | ||
1483 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); | ||
1484 | if (!timer) | ||
1485 | goto out; | ||
1486 | |||
1487 | setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net); | ||
1488 | net->ipv6.ip6_fib_timer = timer; | ||
1489 | |||
1490 | net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL); | ||
1491 | if (!net->ipv6.rt6_stats) | ||
1492 | goto out_timer; | ||
1493 | |||
1494 | net->ipv6.fib_table_hash = | ||
1495 | kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ, | ||
1496 | GFP_KERNEL); | ||
1497 | if (!net->ipv6.fib_table_hash) | ||
1498 | goto out_rt6_stats; | ||
1499 | |||
1500 | net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl), | ||
1501 | GFP_KERNEL); | ||
1502 | if (!net->ipv6.fib6_main_tbl) | ||
1503 | goto out_fib_table_hash; | ||
1504 | |||
1505 | net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN; | ||
1506 | net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry; | ||
1507 | net->ipv6.fib6_main_tbl->tb6_root.fn_flags = | ||
1508 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | ||
1509 | |||
1510 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
1511 | net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl), | ||
1512 | GFP_KERNEL); | ||
1513 | if (!net->ipv6.fib6_local_tbl) | ||
1514 | goto out_fib6_main_tbl; | ||
1515 | net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL; | ||
1516 | net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry; | ||
1517 | net->ipv6.fib6_local_tbl->tb6_root.fn_flags = | ||
1518 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | ||
1519 | #endif | ||
1520 | fib6_tables_init(net); | ||
1521 | |||
1522 | ret = 0; | ||
1523 | out: | ||
1524 | return ret; | ||
1525 | |||
1526 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
1527 | out_fib6_main_tbl: | ||
1528 | kfree(net->ipv6.fib6_main_tbl); | ||
1529 | #endif | ||
1530 | out_fib_table_hash: | ||
1531 | kfree(net->ipv6.fib_table_hash); | ||
1532 | out_rt6_stats: | ||
1533 | kfree(net->ipv6.rt6_stats); | ||
1534 | out_timer: | ||
1535 | kfree(timer); | ||
1536 | goto out; | ||
1537 | } | ||
1538 | |||
1539 | static void fib6_net_exit(struct net *net) | ||
1540 | { | ||
1541 | rt6_ifdown(net, NULL); | ||
1542 | del_timer(net->ipv6.ip6_fib_timer); | ||
1543 | kfree(net->ipv6.ip6_fib_timer); | ||
1544 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
1545 | kfree(net->ipv6.fib6_local_tbl); | ||
1546 | #endif | ||
1547 | kfree(net->ipv6.fib6_main_tbl); | ||
1548 | kfree(net->ipv6.fib_table_hash); | ||
1549 | kfree(net->ipv6.rt6_stats); | ||
1550 | } | ||
1551 | |||
1552 | static struct pernet_operations fib6_net_ops = { | ||
1553 | .init = fib6_net_init, | ||
1554 | .exit = fib6_net_exit, | ||
1555 | }; | ||
1556 | |||
1557 | int __init fib6_init(void) | ||
1558 | { | ||
1559 | int ret = -ENOMEM; | ||
1560 | |||
1483 | fib6_node_kmem = kmem_cache_create("fib6_nodes", | 1561 | fib6_node_kmem = kmem_cache_create("fib6_nodes", |
1484 | sizeof(struct fib6_node), | 1562 | sizeof(struct fib6_node), |
1485 | 0, SLAB_HWCACHE_ALIGN, | 1563 | 0, SLAB_HWCACHE_ALIGN, |
1486 | NULL); | 1564 | NULL); |
1487 | if (!fib6_node_kmem) | 1565 | if (!fib6_node_kmem) |
1488 | return -ENOMEM; | 1566 | goto out; |
1489 | 1567 | ||
1490 | fib6_tables_init(); | 1568 | ret = register_pernet_subsys(&fib6_net_ops); |
1569 | if (ret) | ||
1570 | goto out_kmem_cache_create; | ||
1491 | 1571 | ||
1492 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); | 1572 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); |
1493 | if (ret) | 1573 | if (ret) |
1494 | goto out_kmem_cache_create; | 1574 | goto out_unregister_subsys; |
1495 | out: | 1575 | out: |
1496 | return ret; | 1576 | return ret; |
1497 | 1577 | ||
1578 | out_unregister_subsys: | ||
1579 | unregister_pernet_subsys(&fib6_net_ops); | ||
1498 | out_kmem_cache_create: | 1580 | out_kmem_cache_create: |
1499 | kmem_cache_destroy(fib6_node_kmem); | 1581 | kmem_cache_destroy(fib6_node_kmem); |
1500 | goto out; | 1582 | goto out; |
@@ -1502,6 +1584,6 @@ out_kmem_cache_create: | |||
1502 | 1584 | ||
1503 | void fib6_gc_cleanup(void) | 1585 | void fib6_gc_cleanup(void) |
1504 | { | 1586 | { |
1505 | del_timer(&ip6_fib_timer); | 1587 | unregister_pernet_subsys(&fib6_net_ops); |
1506 | kmem_cache_destroy(fib6_node_kmem); | 1588 | kmem_cache_destroy(fib6_node_kmem); |
1507 | } | 1589 | } |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 2b7d9ee98832..eb7a940310f4 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -62,23 +62,23 @@ static DEFINE_RWLOCK(ip6_fl_lock); | |||
62 | static DEFINE_RWLOCK(ip6_sk_fl_lock); | 62 | static DEFINE_RWLOCK(ip6_sk_fl_lock); |
63 | 63 | ||
64 | 64 | ||
65 | static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label) | 65 | static inline struct ip6_flowlabel *__fl_lookup(struct net *net, __be32 label) |
66 | { | 66 | { |
67 | struct ip6_flowlabel *fl; | 67 | struct ip6_flowlabel *fl; |
68 | 68 | ||
69 | for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) { | 69 | for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) { |
70 | if (fl->label == label) | 70 | if (fl->label == label && fl->fl_net == net) |
71 | return fl; | 71 | return fl; |
72 | } | 72 | } |
73 | return NULL; | 73 | return NULL; |
74 | } | 74 | } |
75 | 75 | ||
76 | static struct ip6_flowlabel * fl_lookup(__be32 label) | 76 | static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label) |
77 | { | 77 | { |
78 | struct ip6_flowlabel *fl; | 78 | struct ip6_flowlabel *fl; |
79 | 79 | ||
80 | read_lock_bh(&ip6_fl_lock); | 80 | read_lock_bh(&ip6_fl_lock); |
81 | fl = __fl_lookup(label); | 81 | fl = __fl_lookup(net, label); |
82 | if (fl) | 82 | if (fl) |
83 | atomic_inc(&fl->users); | 83 | atomic_inc(&fl->users); |
84 | read_unlock_bh(&ip6_fl_lock); | 84 | read_unlock_bh(&ip6_fl_lock); |
@@ -88,8 +88,10 @@ static struct ip6_flowlabel * fl_lookup(__be32 label) | |||
88 | 88 | ||
89 | static void fl_free(struct ip6_flowlabel *fl) | 89 | static void fl_free(struct ip6_flowlabel *fl) |
90 | { | 90 | { |
91 | if (fl) | 91 | if (fl) { |
92 | release_net(fl->fl_net); | ||
92 | kfree(fl->opt); | 93 | kfree(fl->opt); |
94 | } | ||
93 | kfree(fl); | 95 | kfree(fl); |
94 | } | 96 | } |
95 | 97 | ||
@@ -112,7 +114,6 @@ static void fl_release(struct ip6_flowlabel *fl) | |||
112 | time_after(ip6_fl_gc_timer.expires, ttd)) | 114 | time_after(ip6_fl_gc_timer.expires, ttd)) |
113 | mod_timer(&ip6_fl_gc_timer, ttd); | 115 | mod_timer(&ip6_fl_gc_timer, ttd); |
114 | } | 116 | } |
115 | |||
116 | write_unlock_bh(&ip6_fl_lock); | 117 | write_unlock_bh(&ip6_fl_lock); |
117 | } | 118 | } |
118 | 119 | ||
@@ -148,13 +149,34 @@ static void ip6_fl_gc(unsigned long dummy) | |||
148 | if (!sched && atomic_read(&fl_size)) | 149 | if (!sched && atomic_read(&fl_size)) |
149 | sched = now + FL_MAX_LINGER; | 150 | sched = now + FL_MAX_LINGER; |
150 | if (sched) { | 151 | if (sched) { |
151 | ip6_fl_gc_timer.expires = sched; | 152 | mod_timer(&ip6_fl_gc_timer, sched); |
152 | add_timer(&ip6_fl_gc_timer); | 153 | } |
154 | write_unlock(&ip6_fl_lock); | ||
155 | } | ||
156 | |||
157 | static void ip6_fl_purge(struct net *net) | ||
158 | { | ||
159 | int i; | ||
160 | |||
161 | write_lock(&ip6_fl_lock); | ||
162 | for (i = 0; i <= FL_HASH_MASK; i++) { | ||
163 | struct ip6_flowlabel *fl, **flp; | ||
164 | flp = &fl_ht[i]; | ||
165 | while ((fl = *flp) != NULL) { | ||
166 | if (fl->fl_net == net && atomic_read(&fl->users) == 0) { | ||
167 | *flp = fl->next; | ||
168 | fl_free(fl); | ||
169 | atomic_dec(&fl_size); | ||
170 | continue; | ||
171 | } | ||
172 | flp = &fl->next; | ||
173 | } | ||
153 | } | 174 | } |
154 | write_unlock(&ip6_fl_lock); | 175 | write_unlock(&ip6_fl_lock); |
155 | } | 176 | } |
156 | 177 | ||
157 | static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) | 178 | static struct ip6_flowlabel *fl_intern(struct net *net, |
179 | struct ip6_flowlabel *fl, __be32 label) | ||
158 | { | 180 | { |
159 | struct ip6_flowlabel *lfl; | 181 | struct ip6_flowlabel *lfl; |
160 | 182 | ||
@@ -165,7 +187,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) | |||
165 | for (;;) { | 187 | for (;;) { |
166 | fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; | 188 | fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; |
167 | if (fl->label) { | 189 | if (fl->label) { |
168 | lfl = __fl_lookup(fl->label); | 190 | lfl = __fl_lookup(net, fl->label); |
169 | if (lfl == NULL) | 191 | if (lfl == NULL) |
170 | break; | 192 | break; |
171 | } | 193 | } |
@@ -179,7 +201,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) | |||
179 | * done in ipv6_flowlabel_opt - sock is locked, so new entry | 201 | * done in ipv6_flowlabel_opt - sock is locked, so new entry |
180 | * with the same label can only appear on another sock | 202 | * with the same label can only appear on another sock |
181 | */ | 203 | */ |
182 | lfl = __fl_lookup(fl->label); | 204 | lfl = __fl_lookup(net, fl->label); |
183 | if (lfl != NULL) { | 205 | if (lfl != NULL) { |
184 | atomic_inc(&lfl->users); | 206 | atomic_inc(&lfl->users); |
185 | write_unlock_bh(&ip6_fl_lock); | 207 | write_unlock_bh(&ip6_fl_lock); |
@@ -298,7 +320,8 @@ static int fl6_renew(struct ip6_flowlabel *fl, unsigned long linger, unsigned lo | |||
298 | } | 320 | } |
299 | 321 | ||
300 | static struct ip6_flowlabel * | 322 | static struct ip6_flowlabel * |
301 | fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *err_p) | 323 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, |
324 | int optlen, int *err_p) | ||
302 | { | 325 | { |
303 | struct ip6_flowlabel *fl; | 326 | struct ip6_flowlabel *fl; |
304 | int olen; | 327 | int olen; |
@@ -343,6 +366,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int * | |||
343 | } | 366 | } |
344 | } | 367 | } |
345 | 368 | ||
369 | fl->fl_net = hold_net(net); | ||
346 | fl->expires = jiffies; | 370 | fl->expires = jiffies; |
347 | err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); | 371 | err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); |
348 | if (err) | 372 | if (err) |
@@ -441,6 +465,7 @@ static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl, | |||
441 | int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | 465 | int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) |
442 | { | 466 | { |
443 | int err; | 467 | int err; |
468 | struct net *net = sock_net(sk); | ||
444 | struct ipv6_pinfo *np = inet6_sk(sk); | 469 | struct ipv6_pinfo *np = inet6_sk(sk); |
445 | struct in6_flowlabel_req freq; | 470 | struct in6_flowlabel_req freq; |
446 | struct ipv6_fl_socklist *sfl1=NULL; | 471 | struct ipv6_fl_socklist *sfl1=NULL; |
@@ -483,7 +508,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
483 | read_unlock_bh(&ip6_sk_fl_lock); | 508 | read_unlock_bh(&ip6_sk_fl_lock); |
484 | 509 | ||
485 | if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { | 510 | if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { |
486 | fl = fl_lookup(freq.flr_label); | 511 | fl = fl_lookup(net, freq.flr_label); |
487 | if (fl) { | 512 | if (fl) { |
488 | err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); | 513 | err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); |
489 | fl_release(fl); | 514 | fl_release(fl); |
@@ -496,7 +521,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
496 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) | 521 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) |
497 | return -EINVAL; | 522 | return -EINVAL; |
498 | 523 | ||
499 | fl = fl_create(&freq, optval, optlen, &err); | 524 | fl = fl_create(net, &freq, optval, optlen, &err); |
500 | if (fl == NULL) | 525 | if (fl == NULL) |
501 | return err; | 526 | return err; |
502 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); | 527 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); |
@@ -518,7 +543,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
518 | read_unlock_bh(&ip6_sk_fl_lock); | 543 | read_unlock_bh(&ip6_sk_fl_lock); |
519 | 544 | ||
520 | if (fl1 == NULL) | 545 | if (fl1 == NULL) |
521 | fl1 = fl_lookup(freq.flr_label); | 546 | fl1 = fl_lookup(net, freq.flr_label); |
522 | if (fl1) { | 547 | if (fl1) { |
523 | recheck: | 548 | recheck: |
524 | err = -EEXIST; | 549 | err = -EEXIST; |
@@ -559,7 +584,7 @@ release: | |||
559 | if (sfl1 == NULL || (err = mem_check(sk)) != 0) | 584 | if (sfl1 == NULL || (err = mem_check(sk)) != 0) |
560 | goto done; | 585 | goto done; |
561 | 586 | ||
562 | fl1 = fl_intern(fl, freq.flr_label); | 587 | fl1 = fl_intern(net, fl, freq.flr_label); |
563 | if (fl1 != NULL) | 588 | if (fl1 != NULL) |
564 | goto recheck; | 589 | goto recheck; |
565 | 590 | ||
@@ -586,6 +611,7 @@ done: | |||
586 | #ifdef CONFIG_PROC_FS | 611 | #ifdef CONFIG_PROC_FS |
587 | 612 | ||
588 | struct ip6fl_iter_state { | 613 | struct ip6fl_iter_state { |
614 | struct seq_net_private p; | ||
589 | int bucket; | 615 | int bucket; |
590 | }; | 616 | }; |
591 | 617 | ||
@@ -595,12 +621,15 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq) | |||
595 | { | 621 | { |
596 | struct ip6_flowlabel *fl = NULL; | 622 | struct ip6_flowlabel *fl = NULL; |
597 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 623 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
624 | struct net *net = seq_file_net(seq); | ||
598 | 625 | ||
599 | for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { | 626 | for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { |
600 | if (fl_ht[state->bucket]) { | 627 | fl = fl_ht[state->bucket]; |
601 | fl = fl_ht[state->bucket]; | 628 | |
629 | while (fl && fl->fl_net != net) | ||
630 | fl = fl->next; | ||
631 | if (fl) | ||
602 | break; | 632 | break; |
603 | } | ||
604 | } | 633 | } |
605 | return fl; | 634 | return fl; |
606 | } | 635 | } |
@@ -608,12 +637,18 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq) | |||
608 | static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl) | 637 | static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl) |
609 | { | 638 | { |
610 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 639 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
640 | struct net *net = seq_file_net(seq); | ||
611 | 641 | ||
612 | fl = fl->next; | 642 | fl = fl->next; |
643 | try_again: | ||
644 | while (fl && fl->fl_net != net) | ||
645 | fl = fl->next; | ||
646 | |||
613 | while (!fl) { | 647 | while (!fl) { |
614 | if (++state->bucket <= FL_HASH_MASK) | 648 | if (++state->bucket <= FL_HASH_MASK) { |
615 | fl = fl_ht[state->bucket]; | 649 | fl = fl_ht[state->bucket]; |
616 | else | 650 | goto try_again; |
651 | } else | ||
617 | break; | 652 | break; |
618 | } | 653 | } |
619 | return fl; | 654 | return fl; |
@@ -683,8 +718,8 @@ static const struct seq_operations ip6fl_seq_ops = { | |||
683 | 718 | ||
684 | static int ip6fl_seq_open(struct inode *inode, struct file *file) | 719 | static int ip6fl_seq_open(struct inode *inode, struct file *file) |
685 | { | 720 | { |
686 | return seq_open_private(file, &ip6fl_seq_ops, | 721 | return seq_open_net(inode, file, &ip6fl_seq_ops, |
687 | sizeof(struct ip6fl_iter_state)); | 722 | sizeof(struct ip6fl_iter_state)); |
688 | } | 723 | } |
689 | 724 | ||
690 | static const struct file_operations ip6fl_seq_fops = { | 725 | static const struct file_operations ip6fl_seq_fops = { |
@@ -692,12 +727,13 @@ static const struct file_operations ip6fl_seq_fops = { | |||
692 | .open = ip6fl_seq_open, | 727 | .open = ip6fl_seq_open, |
693 | .read = seq_read, | 728 | .read = seq_read, |
694 | .llseek = seq_lseek, | 729 | .llseek = seq_lseek, |
695 | .release = seq_release_private, | 730 | .release = seq_release_net, |
696 | }; | 731 | }; |
697 | 732 | ||
698 | static int ip6_flowlabel_proc_init(struct net *net) | 733 | static int ip6_flowlabel_proc_init(struct net *net) |
699 | { | 734 | { |
700 | if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops)) | 735 | if (!proc_net_fops_create(net, "ip6_flowlabel", |
736 | S_IRUGO, &ip6fl_seq_fops)) | ||
701 | return -ENOMEM; | 737 | return -ENOMEM; |
702 | return 0; | 738 | return 0; |
703 | } | 739 | } |
@@ -717,13 +753,24 @@ static inline void ip6_flowlabel_proc_fini(struct net *net) | |||
717 | } | 753 | } |
718 | #endif | 754 | #endif |
719 | 755 | ||
756 | static inline void ip6_flowlabel_net_exit(struct net *net) | ||
757 | { | ||
758 | ip6_fl_purge(net); | ||
759 | ip6_flowlabel_proc_fini(net); | ||
760 | } | ||
761 | |||
762 | static struct pernet_operations ip6_flowlabel_net_ops = { | ||
763 | .init = ip6_flowlabel_proc_init, | ||
764 | .exit = ip6_flowlabel_net_exit, | ||
765 | }; | ||
766 | |||
720 | int ip6_flowlabel_init(void) | 767 | int ip6_flowlabel_init(void) |
721 | { | 768 | { |
722 | return ip6_flowlabel_proc_init(&init_net); | 769 | return register_pernet_subsys(&ip6_flowlabel_net_ops); |
723 | } | 770 | } |
724 | 771 | ||
725 | void ip6_flowlabel_cleanup(void) | 772 | void ip6_flowlabel_cleanup(void) |
726 | { | 773 | { |
727 | del_timer(&ip6_fl_gc_timer); | 774 | del_timer(&ip6_fl_gc_timer); |
728 | ip6_flowlabel_proc_fini(&init_net); | 775 | unregister_pernet_subsys(&ip6_flowlabel_net_ops); |
729 | } | 776 | } |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 98ab4f459905..4e5c8615832c 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
30 | #include <linux/in6.h> | 30 | #include <linux/in6.h> |
31 | #include <linux/icmpv6.h> | 31 | #include <linux/icmpv6.h> |
32 | #include <linux/mroute6.h> | ||
32 | 33 | ||
33 | #include <linux/netfilter.h> | 34 | #include <linux/netfilter.h> |
34 | #include <linux/netfilter_ipv6.h> | 35 | #include <linux/netfilter_ipv6.h> |
@@ -61,11 +62,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
61 | u32 pkt_len; | 62 | u32 pkt_len; |
62 | struct inet6_dev *idev; | 63 | struct inet6_dev *idev; |
63 | 64 | ||
64 | if (dev->nd_net != &init_net) { | ||
65 | kfree_skb(skb); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | if (skb->pkt_type == PACKET_OTHERHOST) { | 65 | if (skb->pkt_type == PACKET_OTHERHOST) { |
70 | kfree_skb(skb); | 66 | kfree_skb(skb); |
71 | return 0; | 67 | return 0; |
@@ -241,38 +237,84 @@ int ip6_mc_input(struct sk_buff *skb) | |||
241 | hdr = ipv6_hdr(skb); | 237 | hdr = ipv6_hdr(skb); |
242 | deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); | 238 | deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); |
243 | 239 | ||
240 | #ifdef CONFIG_IPV6_MROUTE | ||
244 | /* | 241 | /* |
245 | * IPv6 multicast router mode isnt currently supported. | 242 | * IPv6 multicast router mode is now supported ;) |
246 | */ | 243 | */ |
247 | #if 0 | 244 | if (ipv6_devconf.mc_forwarding && |
248 | if (ipv6_config.multicast_route) { | 245 | likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { |
249 | int addr_type; | 246 | /* |
250 | 247 | * Okay, we try to forward - split and duplicate | |
251 | addr_type = ipv6_addr_type(&hdr->daddr); | 248 | * packets. |
252 | 249 | */ | |
253 | if (!(addr_type & (IPV6_ADDR_LOOPBACK | IPV6_ADDR_LINKLOCAL))) { | 250 | struct sk_buff *skb2; |
254 | struct sk_buff *skb2; | 251 | struct inet6_skb_parm *opt = IP6CB(skb); |
255 | struct dst_entry *dst; | 252 | |
253 | /* Check for MLD */ | ||
254 | if (unlikely(opt->ra)) { | ||
255 | /* Check if this is a mld message */ | ||
256 | u8 *ptr = skb_network_header(skb) + opt->ra; | ||
257 | struct icmp6hdr *icmp6; | ||
258 | u8 nexthdr = hdr->nexthdr; | ||
259 | int offset; | ||
260 | |||
261 | /* Check if the value of Router Alert | ||
262 | * is for MLD (0x0000). | ||
263 | */ | ||
264 | if ((ptr[2] | ptr[3]) == 0) { | ||
265 | deliver = 0; | ||
266 | |||
267 | if (!ipv6_ext_hdr(nexthdr)) { | ||
268 | /* BUG */ | ||
269 | goto out; | ||
270 | } | ||
271 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), | ||
272 | &nexthdr); | ||
273 | if (offset < 0) | ||
274 | goto out; | ||
275 | |||
276 | if (nexthdr != IPPROTO_ICMPV6) | ||
277 | goto out; | ||
278 | |||
279 | if (!pskb_may_pull(skb, (skb_network_header(skb) + | ||
280 | offset + 1 - skb->data))) | ||
281 | goto out; | ||
282 | |||
283 | icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); | ||
284 | |||
285 | switch (icmp6->icmp6_type) { | ||
286 | case ICMPV6_MGM_QUERY: | ||
287 | case ICMPV6_MGM_REPORT: | ||
288 | case ICMPV6_MGM_REDUCTION: | ||
289 | case ICMPV6_MLD2_REPORT: | ||
290 | deliver = 1; | ||
291 | break; | ||
292 | } | ||
293 | goto out; | ||
294 | } | ||
295 | /* unknown RA - process it normally */ | ||
296 | } | ||
256 | 297 | ||
257 | dst = skb->dst; | 298 | if (deliver) |
299 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
300 | else { | ||
301 | skb2 = skb; | ||
302 | skb = NULL; | ||
303 | } | ||
258 | 304 | ||
259 | if (deliver) { | 305 | if (skb2) { |
260 | skb2 = skb_clone(skb, GFP_ATOMIC); | 306 | skb2->dev = skb2->dst->dev; |
261 | dst_output(skb2); | 307 | ip6_mr_input(skb2); |
262 | } else { | ||
263 | dst_output(skb); | ||
264 | return 0; | ||
265 | } | ||
266 | } | 308 | } |
267 | } | 309 | } |
310 | out: | ||
268 | #endif | 311 | #endif |
269 | 312 | if (likely(deliver)) | |
270 | if (likely(deliver)) { | ||
271 | ip6_input(skb); | 313 | ip6_input(skb); |
272 | return 0; | 314 | else { |
315 | /* discard */ | ||
316 | kfree_skb(skb); | ||
273 | } | 317 | } |
274 | /* discard */ | ||
275 | kfree_skb(skb); | ||
276 | 318 | ||
277 | return 0; | 319 | return 0; |
278 | } | 320 | } |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 8b67ca07467d..0af2e055f883 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <net/icmp.h> | 55 | #include <net/icmp.h> |
56 | #include <net/xfrm.h> | 56 | #include <net/xfrm.h> |
57 | #include <net/checksum.h> | 57 | #include <net/checksum.h> |
58 | #include <linux/mroute6.h> | ||
58 | 59 | ||
59 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); | 60 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); |
60 | 61 | ||
@@ -137,8 +138,9 @@ static int ip6_output2(struct sk_buff *skb) | |||
137 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); | 138 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); |
138 | 139 | ||
139 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && | 140 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
140 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, | 141 | ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
141 | &ipv6_hdr(skb)->saddr)) { | 142 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
143 | &ipv6_hdr(skb)->saddr))) { | ||
142 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 144 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
143 | 145 | ||
144 | /* Do not check for IFF_ALLMULTI; multicast routing | 146 | /* Do not check for IFF_ALLMULTI; multicast routing |
@@ -237,9 +239,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
237 | if (np) | 239 | if (np) |
238 | hlimit = np->hop_limit; | 240 | hlimit = np->hop_limit; |
239 | if (hlimit < 0) | 241 | if (hlimit < 0) |
240 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 242 | hlimit = ip6_dst_hoplimit(dst); |
241 | if (hlimit < 0) | ||
242 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
243 | 243 | ||
244 | tclass = -1; | 244 | tclass = -1; |
245 | if (np) | 245 | if (np) |
@@ -286,7 +286,7 @@ EXPORT_SYMBOL(ip6_xmit); | |||
286 | */ | 286 | */ |
287 | 287 | ||
288 | int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | 288 | int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, |
289 | struct in6_addr *saddr, struct in6_addr *daddr, | 289 | const struct in6_addr *saddr, const struct in6_addr *daddr, |
290 | int proto, int len) | 290 | int proto, int len) |
291 | { | 291 | { |
292 | struct ipv6_pinfo *np = inet6_sk(sk); | 292 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -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 = dev_net(dst->dev); | ||
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,19 @@ 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 = sock_net(sk); | ||
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, | ||
926 | sk ? inet6_sk(sk)->srcprefs : 0, | ||
927 | &fl->fl6_src); | ||
924 | if (err) | 928 | if (err) |
925 | goto out_err_release; | 929 | goto out_err_release; |
926 | } | 930 | } |
@@ -939,7 +943,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
939 | struct flowi fl_gw; | 943 | struct flowi fl_gw; |
940 | int redirect; | 944 | int redirect; |
941 | 945 | ||
942 | ifp = ipv6_get_ifaddr(&init_net, &fl->fl6_src, | 946 | ifp = ipv6_get_ifaddr(net, &fl->fl6_src, |
943 | (*dst)->dev, 1); | 947 | (*dst)->dev, 1); |
944 | 948 | ||
945 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); | 949 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); |
@@ -954,7 +958,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
954 | dst_release(*dst); | 958 | dst_release(*dst); |
955 | memcpy(&fl_gw, fl, sizeof(struct flowi)); | 959 | memcpy(&fl_gw, fl, sizeof(struct flowi)); |
956 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); | 960 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); |
957 | *dst = ip6_route_output(sk, &fl_gw); | 961 | *dst = ip6_route_output(net, sk, &fl_gw); |
958 | if ((err = (*dst)->error)) | 962 | if ((err = (*dst)->error)) |
959 | goto out_err_release; | 963 | goto out_err_release; |
960 | } | 964 | } |
@@ -1113,7 +1117,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1113 | /* need source address above miyazawa*/ | 1117 | /* need source address above miyazawa*/ |
1114 | } | 1118 | } |
1115 | dst_hold(&rt->u.dst); | 1119 | dst_hold(&rt->u.dst); |
1116 | np->cork.rt = rt; | 1120 | inet->cork.dst = &rt->u.dst; |
1117 | inet->cork.fl = *fl; | 1121 | inet->cork.fl = *fl; |
1118 | np->cork.hop_limit = hlimit; | 1122 | np->cork.hop_limit = hlimit; |
1119 | np->cork.tclass = tclass; | 1123 | np->cork.tclass = tclass; |
@@ -1134,7 +1138,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1134 | length += exthdrlen; | 1138 | length += exthdrlen; |
1135 | transhdrlen += exthdrlen; | 1139 | transhdrlen += exthdrlen; |
1136 | } else { | 1140 | } else { |
1137 | rt = np->cork.rt; | 1141 | rt = (struct rt6_info *)inet->cork.dst; |
1138 | fl = &inet->cork.fl; | 1142 | fl = &inet->cork.fl; |
1139 | if (inet->cork.flags & IPCORK_OPT) | 1143 | if (inet->cork.flags & IPCORK_OPT) |
1140 | opt = np->cork.opt; | 1144 | opt = np->cork.opt; |
@@ -1379,9 +1383,9 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) | |||
1379 | inet->cork.flags &= ~IPCORK_OPT; | 1383 | inet->cork.flags &= ~IPCORK_OPT; |
1380 | kfree(np->cork.opt); | 1384 | kfree(np->cork.opt); |
1381 | np->cork.opt = NULL; | 1385 | np->cork.opt = NULL; |
1382 | if (np->cork.rt) { | 1386 | if (inet->cork.dst) { |
1383 | dst_release(&np->cork.rt->u.dst); | 1387 | dst_release(inet->cork.dst); |
1384 | np->cork.rt = NULL; | 1388 | inet->cork.dst = NULL; |
1385 | inet->cork.flags &= ~IPCORK_ALLFRAG; | 1389 | inet->cork.flags &= ~IPCORK_ALLFRAG; |
1386 | } | 1390 | } |
1387 | memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); | 1391 | memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); |
@@ -1396,7 +1400,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1396 | struct ipv6_pinfo *np = inet6_sk(sk); | 1400 | struct ipv6_pinfo *np = inet6_sk(sk); |
1397 | struct ipv6hdr *hdr; | 1401 | struct ipv6hdr *hdr; |
1398 | struct ipv6_txoptions *opt = np->cork.opt; | 1402 | struct ipv6_txoptions *opt = np->cork.opt; |
1399 | struct rt6_info *rt = np->cork.rt; | 1403 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; |
1400 | struct flowi *fl = &inet->cork.fl; | 1404 | struct flowi *fl = &inet->cork.fl; |
1401 | unsigned char proto = fl->proto; | 1405 | unsigned char proto = fl->proto; |
1402 | int err = 0; | 1406 | int err = 0; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 78f438880923..61517fe0c57c 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -60,7 +60,7 @@ MODULE_LICENSE("GPL"); | |||
60 | #define IPV6_TLV_TEL_DST_SIZE 8 | 60 | #define IPV6_TLV_TEL_DST_SIZE 8 |
61 | 61 | ||
62 | #ifdef IP6_TNL_DEBUG | 62 | #ifdef IP6_TNL_DEBUG |
63 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__) | 63 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) |
64 | #else | 64 | #else |
65 | #define IP6_TNL_TRACE(x...) do {;} while(0) | 65 | #define IP6_TNL_TRACE(x...) do {;} while(0) |
66 | #endif | 66 | #endif |
@@ -602,7 +602,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
602 | skb_reset_network_header(skb2); | 602 | skb_reset_network_header(skb2); |
603 | 603 | ||
604 | /* Try to guess incoming interface */ | 604 | /* Try to guess incoming interface */ |
605 | rt = rt6_lookup(&ipv6_hdr(skb2)->saddr, NULL, 0, 0); | 605 | rt = rt6_lookup(&init_net, &ipv6_hdr(skb2)->saddr, NULL, 0, 0); |
606 | 606 | ||
607 | if (rt && rt->rt6i_dev) | 607 | if (rt && rt->rt6i_dev) |
608 | skb2->dev = rt->rt6i_dev; | 608 | skb2->dev = rt->rt6i_dev; |
@@ -847,7 +847,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
847 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 847 | if ((dst = ip6_tnl_dst_check(t)) != NULL) |
848 | dst_hold(dst); | 848 | dst_hold(dst); |
849 | else { | 849 | else { |
850 | dst = ip6_route_output(NULL, fl); | 850 | dst = ip6_route_output(&init_net, NULL, fl); |
851 | 851 | ||
852 | if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0) | 852 | if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0) |
853 | goto tx_err_link_failure; | 853 | goto tx_err_link_failure; |
@@ -1112,7 +1112,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1112 | int strict = (ipv6_addr_type(&p->raddr) & | 1112 | int strict = (ipv6_addr_type(&p->raddr) & |
1113 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); | 1113 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); |
1114 | 1114 | ||
1115 | struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr, | 1115 | struct rt6_info *rt = rt6_lookup(&init_net, &p->raddr, &p->laddr, |
1116 | p->link, strict); | 1116 | p->link, strict); |
1117 | 1117 | ||
1118 | if (rt == NULL) | 1118 | if (rt == NULL) |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c new file mode 100644 index 000000000000..c8c6e33d1163 --- /dev/null +++ b/net/ipv6/ip6mr.c | |||
@@ -0,0 +1,1643 @@ | |||
1 | /* | ||
2 | * Linux IPv6 multicast routing support for BSD pim6sd | ||
3 | * Based on net/ipv4/ipmr.c. | ||
4 | * | ||
5 | * (c) 2004 Mickael Hoerdt, <hoerdt@clarinet.u-strasbg.fr> | ||
6 | * LSIIT Laboratory, Strasbourg, France | ||
7 | * (c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot@6WIND.com> | ||
8 | * 6WIND, Paris, France | ||
9 | * Copyright (C)2007,2008 USAGI/WIDE Project | ||
10 | * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <asm/system.h> | ||
20 | #include <asm/uaccess.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/timer.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/fcntl.h> | ||
28 | #include <linux/stat.h> | ||
29 | #include <linux/socket.h> | ||
30 | #include <linux/inet.h> | ||
31 | #include <linux/netdevice.h> | ||
32 | #include <linux/inetdevice.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <net/protocol.h> | ||
37 | #include <linux/skbuff.h> | ||
38 | #include <net/sock.h> | ||
39 | #include <net/raw.h> | ||
40 | #include <linux/notifier.h> | ||
41 | #include <linux/if_arp.h> | ||
42 | #include <net/checksum.h> | ||
43 | #include <net/netlink.h> | ||
44 | |||
45 | #include <net/ipv6.h> | ||
46 | #include <net/ip6_route.h> | ||
47 | #include <linux/mroute6.h> | ||
48 | #include <linux/pim.h> | ||
49 | #include <net/addrconf.h> | ||
50 | #include <linux/netfilter_ipv6.h> | ||
51 | |||
52 | struct sock *mroute6_socket; | ||
53 | |||
54 | |||
55 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | ||
56 | Note that the changes are semaphored via rtnl_lock. | ||
57 | */ | ||
58 | |||
59 | static DEFINE_RWLOCK(mrt_lock); | ||
60 | |||
61 | /* | ||
62 | * Multicast router control variables | ||
63 | */ | ||
64 | |||
65 | static struct mif_device vif6_table[MAXMIFS]; /* Devices */ | ||
66 | static int maxvif; | ||
67 | |||
68 | #define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL) | ||
69 | |||
70 | static int mroute_do_assert; /* Set in PIM assert */ | ||
71 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
72 | static int mroute_do_pim; | ||
73 | #else | ||
74 | #define mroute_do_pim 0 | ||
75 | #endif | ||
76 | |||
77 | static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */ | ||
78 | |||
79 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ | ||
80 | static atomic_t cache_resolve_queue_len; /* Size of unresolved */ | ||
81 | |||
82 | /* Special spinlock for queue of unresolved entries */ | ||
83 | static DEFINE_SPINLOCK(mfc_unres_lock); | ||
84 | |||
85 | /* We return to original Alan's scheme. Hash table of resolved | ||
86 | entries is changed only in process context and protected | ||
87 | with weak lock mrt_lock. Queue of unresolved entries is protected | ||
88 | with strong spinlock mfc_unres_lock. | ||
89 | |||
90 | In this case data path is free of exclusive locks at all. | ||
91 | */ | ||
92 | |||
93 | static struct kmem_cache *mrt_cachep __read_mostly; | ||
94 | |||
95 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache); | ||
96 | static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert); | ||
97 | static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); | ||
98 | |||
99 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
100 | static struct inet6_protocol pim6_protocol; | ||
101 | #endif | ||
102 | |||
103 | static struct timer_list ipmr_expire_timer; | ||
104 | |||
105 | |||
106 | #ifdef CONFIG_PROC_FS | ||
107 | |||
108 | struct ipmr_mfc_iter { | ||
109 | struct mfc6_cache **cache; | ||
110 | int ct; | ||
111 | }; | ||
112 | |||
113 | |||
114 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | ||
115 | { | ||
116 | struct mfc6_cache *mfc; | ||
117 | |||
118 | it->cache = mfc6_cache_array; | ||
119 | read_lock(&mrt_lock); | ||
120 | for (it->ct = 0; it->ct < ARRAY_SIZE(mfc6_cache_array); it->ct++) | ||
121 | for (mfc = mfc6_cache_array[it->ct]; mfc; mfc = mfc->next) | ||
122 | if (pos-- == 0) | ||
123 | return mfc; | ||
124 | read_unlock(&mrt_lock); | ||
125 | |||
126 | it->cache = &mfc_unres_queue; | ||
127 | spin_lock_bh(&mfc_unres_lock); | ||
128 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | ||
129 | if (pos-- == 0) | ||
130 | return mfc; | ||
131 | spin_unlock_bh(&mfc_unres_lock); | ||
132 | |||
133 | it->cache = NULL; | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | |||
138 | |||
139 | |||
140 | /* | ||
141 | * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif | ||
142 | */ | ||
143 | |||
144 | struct ipmr_vif_iter { | ||
145 | int ct; | ||
146 | }; | ||
147 | |||
148 | static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, | ||
149 | loff_t pos) | ||
150 | { | ||
151 | for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { | ||
152 | if (!MIF_EXISTS(iter->ct)) | ||
153 | continue; | ||
154 | if (pos-- == 0) | ||
155 | return &vif6_table[iter->ct]; | ||
156 | } | ||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) | ||
161 | __acquires(mrt_lock) | ||
162 | { | ||
163 | read_lock(&mrt_lock); | ||
164 | return (*pos ? ip6mr_vif_seq_idx(seq->private, *pos - 1) | ||
165 | : SEQ_START_TOKEN); | ||
166 | } | ||
167 | |||
168 | static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
169 | { | ||
170 | struct ipmr_vif_iter *iter = seq->private; | ||
171 | |||
172 | ++*pos; | ||
173 | if (v == SEQ_START_TOKEN) | ||
174 | return ip6mr_vif_seq_idx(iter, 0); | ||
175 | |||
176 | while (++iter->ct < maxvif) { | ||
177 | if (!MIF_EXISTS(iter->ct)) | ||
178 | continue; | ||
179 | return &vif6_table[iter->ct]; | ||
180 | } | ||
181 | return NULL; | ||
182 | } | ||
183 | |||
184 | static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v) | ||
185 | __releases(mrt_lock) | ||
186 | { | ||
187 | read_unlock(&mrt_lock); | ||
188 | } | ||
189 | |||
190 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | ||
191 | { | ||
192 | if (v == SEQ_START_TOKEN) { | ||
193 | seq_puts(seq, | ||
194 | "Interface BytesIn PktsIn BytesOut PktsOut Flags\n"); | ||
195 | } else { | ||
196 | const struct mif_device *vif = v; | ||
197 | const char *name = vif->dev ? vif->dev->name : "none"; | ||
198 | |||
199 | seq_printf(seq, | ||
200 | "%2Zd %-10s %8ld %7ld %8ld %7ld %05X\n", | ||
201 | vif - vif6_table, | ||
202 | name, vif->bytes_in, vif->pkt_in, | ||
203 | vif->bytes_out, vif->pkt_out, | ||
204 | vif->flags); | ||
205 | } | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static struct seq_operations ip6mr_vif_seq_ops = { | ||
210 | .start = ip6mr_vif_seq_start, | ||
211 | .next = ip6mr_vif_seq_next, | ||
212 | .stop = ip6mr_vif_seq_stop, | ||
213 | .show = ip6mr_vif_seq_show, | ||
214 | }; | ||
215 | |||
216 | static int ip6mr_vif_open(struct inode *inode, struct file *file) | ||
217 | { | ||
218 | return seq_open_private(file, &ip6mr_vif_seq_ops, | ||
219 | sizeof(struct ipmr_vif_iter)); | ||
220 | } | ||
221 | |||
222 | static struct file_operations ip6mr_vif_fops = { | ||
223 | .owner = THIS_MODULE, | ||
224 | .open = ip6mr_vif_open, | ||
225 | .read = seq_read, | ||
226 | .llseek = seq_lseek, | ||
227 | .release = seq_release, | ||
228 | }; | ||
229 | |||
230 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) | ||
231 | { | ||
232 | return (*pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1) | ||
233 | : SEQ_START_TOKEN); | ||
234 | } | ||
235 | |||
236 | static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
237 | { | ||
238 | struct mfc6_cache *mfc = v; | ||
239 | struct ipmr_mfc_iter *it = seq->private; | ||
240 | |||
241 | ++*pos; | ||
242 | |||
243 | if (v == SEQ_START_TOKEN) | ||
244 | return ipmr_mfc_seq_idx(seq->private, 0); | ||
245 | |||
246 | if (mfc->next) | ||
247 | return mfc->next; | ||
248 | |||
249 | if (it->cache == &mfc_unres_queue) | ||
250 | goto end_of_list; | ||
251 | |||
252 | BUG_ON(it->cache != mfc6_cache_array); | ||
253 | |||
254 | while (++it->ct < ARRAY_SIZE(mfc6_cache_array)) { | ||
255 | mfc = mfc6_cache_array[it->ct]; | ||
256 | if (mfc) | ||
257 | return mfc; | ||
258 | } | ||
259 | |||
260 | /* exhausted cache_array, show unresolved */ | ||
261 | read_unlock(&mrt_lock); | ||
262 | it->cache = &mfc_unres_queue; | ||
263 | it->ct = 0; | ||
264 | |||
265 | spin_lock_bh(&mfc_unres_lock); | ||
266 | mfc = mfc_unres_queue; | ||
267 | if (mfc) | ||
268 | return mfc; | ||
269 | |||
270 | end_of_list: | ||
271 | spin_unlock_bh(&mfc_unres_lock); | ||
272 | it->cache = NULL; | ||
273 | |||
274 | return NULL; | ||
275 | } | ||
276 | |||
277 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | ||
278 | { | ||
279 | struct ipmr_mfc_iter *it = seq->private; | ||
280 | |||
281 | if (it->cache == &mfc_unres_queue) | ||
282 | spin_unlock_bh(&mfc_unres_lock); | ||
283 | else if (it->cache == mfc6_cache_array) | ||
284 | read_unlock(&mrt_lock); | ||
285 | } | ||
286 | |||
287 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | ||
288 | { | ||
289 | int n; | ||
290 | |||
291 | if (v == SEQ_START_TOKEN) { | ||
292 | seq_puts(seq, | ||
293 | "Group " | ||
294 | "Origin " | ||
295 | "Iif Pkts Bytes Wrong Oifs\n"); | ||
296 | } else { | ||
297 | const struct mfc6_cache *mfc = v; | ||
298 | const struct ipmr_mfc_iter *it = seq->private; | ||
299 | |||
300 | seq_printf(seq, | ||
301 | NIP6_FMT " " NIP6_FMT " %-3d %8ld %8ld %8ld", | ||
302 | NIP6(mfc->mf6c_mcastgrp), NIP6(mfc->mf6c_origin), | ||
303 | mfc->mf6c_parent, | ||
304 | mfc->mfc_un.res.pkt, | ||
305 | mfc->mfc_un.res.bytes, | ||
306 | mfc->mfc_un.res.wrong_if); | ||
307 | |||
308 | if (it->cache != &mfc_unres_queue) { | ||
309 | for (n = mfc->mfc_un.res.minvif; | ||
310 | n < mfc->mfc_un.res.maxvif; n++) { | ||
311 | if (MIF_EXISTS(n) && | ||
312 | mfc->mfc_un.res.ttls[n] < 255) | ||
313 | seq_printf(seq, | ||
314 | " %2d:%-3d", | ||
315 | n, mfc->mfc_un.res.ttls[n]); | ||
316 | } | ||
317 | } | ||
318 | seq_putc(seq, '\n'); | ||
319 | } | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static struct seq_operations ipmr_mfc_seq_ops = { | ||
324 | .start = ipmr_mfc_seq_start, | ||
325 | .next = ipmr_mfc_seq_next, | ||
326 | .stop = ipmr_mfc_seq_stop, | ||
327 | .show = ipmr_mfc_seq_show, | ||
328 | }; | ||
329 | |||
330 | static int ipmr_mfc_open(struct inode *inode, struct file *file) | ||
331 | { | ||
332 | return seq_open_private(file, &ipmr_mfc_seq_ops, | ||
333 | sizeof(struct ipmr_mfc_iter)); | ||
334 | } | ||
335 | |||
336 | static struct file_operations ip6mr_mfc_fops = { | ||
337 | .owner = THIS_MODULE, | ||
338 | .open = ipmr_mfc_open, | ||
339 | .read = seq_read, | ||
340 | .llseek = seq_lseek, | ||
341 | .release = seq_release, | ||
342 | }; | ||
343 | #endif | ||
344 | |||
345 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
346 | static int reg_vif_num = -1; | ||
347 | |||
348 | static int pim6_rcv(struct sk_buff *skb) | ||
349 | { | ||
350 | struct pimreghdr *pim; | ||
351 | struct ipv6hdr *encap; | ||
352 | struct net_device *reg_dev = NULL; | ||
353 | |||
354 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) | ||
355 | goto drop; | ||
356 | |||
357 | pim = (struct pimreghdr *)skb_transport_header(skb); | ||
358 | if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || | ||
359 | (pim->flags & PIM_NULL_REGISTER) || | ||
360 | (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && | ||
361 | (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | ||
362 | goto drop; | ||
363 | |||
364 | /* check if the inner packet is destined to mcast group */ | ||
365 | encap = (struct ipv6hdr *)(skb_transport_header(skb) + | ||
366 | sizeof(*pim)); | ||
367 | |||
368 | if (!ipv6_addr_is_multicast(&encap->daddr) || | ||
369 | encap->payload_len == 0 || | ||
370 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) | ||
371 | goto drop; | ||
372 | |||
373 | read_lock(&mrt_lock); | ||
374 | if (reg_vif_num >= 0) | ||
375 | reg_dev = vif6_table[reg_vif_num].dev; | ||
376 | if (reg_dev) | ||
377 | dev_hold(reg_dev); | ||
378 | read_unlock(&mrt_lock); | ||
379 | |||
380 | if (reg_dev == NULL) | ||
381 | goto drop; | ||
382 | |||
383 | skb->mac_header = skb->network_header; | ||
384 | skb_pull(skb, (u8 *)encap - skb->data); | ||
385 | skb_reset_network_header(skb); | ||
386 | skb->dev = reg_dev; | ||
387 | skb->protocol = htons(ETH_P_IP); | ||
388 | skb->ip_summed = 0; | ||
389 | skb->pkt_type = PACKET_HOST; | ||
390 | dst_release(skb->dst); | ||
391 | ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len; | ||
392 | ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++; | ||
393 | skb->dst = NULL; | ||
394 | nf_reset(skb); | ||
395 | netif_rx(skb); | ||
396 | dev_put(reg_dev); | ||
397 | return 0; | ||
398 | drop: | ||
399 | kfree_skb(skb); | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static struct inet6_protocol pim6_protocol = { | ||
404 | .handler = pim6_rcv, | ||
405 | }; | ||
406 | |||
407 | /* Service routines creating virtual interfaces: PIMREG */ | ||
408 | |||
409 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | ||
410 | { | ||
411 | read_lock(&mrt_lock); | ||
412 | ((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len; | ||
413 | ((struct net_device_stats *)netdev_priv(dev))->tx_packets++; | ||
414 | ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT); | ||
415 | read_unlock(&mrt_lock); | ||
416 | kfree_skb(skb); | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) | ||
421 | { | ||
422 | return (struct net_device_stats *)netdev_priv(dev); | ||
423 | } | ||
424 | |||
425 | static void reg_vif_setup(struct net_device *dev) | ||
426 | { | ||
427 | dev->type = ARPHRD_PIMREG; | ||
428 | dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; | ||
429 | dev->flags = IFF_NOARP; | ||
430 | dev->hard_start_xmit = reg_vif_xmit; | ||
431 | dev->get_stats = reg_vif_get_stats; | ||
432 | dev->destructor = free_netdev; | ||
433 | } | ||
434 | |||
435 | static struct net_device *ip6mr_reg_vif(void) | ||
436 | { | ||
437 | struct net_device *dev; | ||
438 | |||
439 | dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg", | ||
440 | reg_vif_setup); | ||
441 | |||
442 | if (dev == NULL) | ||
443 | return NULL; | ||
444 | |||
445 | if (register_netdevice(dev)) { | ||
446 | free_netdev(dev); | ||
447 | return NULL; | ||
448 | } | ||
449 | dev->iflink = 0; | ||
450 | |||
451 | if (dev_open(dev)) | ||
452 | goto failure; | ||
453 | |||
454 | return dev; | ||
455 | |||
456 | failure: | ||
457 | /* allow the register to be completed before unregistering. */ | ||
458 | rtnl_unlock(); | ||
459 | rtnl_lock(); | ||
460 | |||
461 | unregister_netdevice(dev); | ||
462 | return NULL; | ||
463 | } | ||
464 | #endif | ||
465 | |||
466 | /* | ||
467 | * Delete a VIF entry | ||
468 | */ | ||
469 | |||
470 | static int mif6_delete(int vifi) | ||
471 | { | ||
472 | struct mif_device *v; | ||
473 | struct net_device *dev; | ||
474 | if (vifi < 0 || vifi >= maxvif) | ||
475 | return -EADDRNOTAVAIL; | ||
476 | |||
477 | v = &vif6_table[vifi]; | ||
478 | |||
479 | write_lock_bh(&mrt_lock); | ||
480 | dev = v->dev; | ||
481 | v->dev = NULL; | ||
482 | |||
483 | if (!dev) { | ||
484 | write_unlock_bh(&mrt_lock); | ||
485 | return -EADDRNOTAVAIL; | ||
486 | } | ||
487 | |||
488 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
489 | if (vifi == reg_vif_num) | ||
490 | reg_vif_num = -1; | ||
491 | #endif | ||
492 | |||
493 | if (vifi + 1 == maxvif) { | ||
494 | int tmp; | ||
495 | for (tmp = vifi - 1; tmp >= 0; tmp--) { | ||
496 | if (MIF_EXISTS(tmp)) | ||
497 | break; | ||
498 | } | ||
499 | maxvif = tmp + 1; | ||
500 | } | ||
501 | |||
502 | write_unlock_bh(&mrt_lock); | ||
503 | |||
504 | dev_set_allmulti(dev, -1); | ||
505 | |||
506 | if (v->flags & MIFF_REGISTER) | ||
507 | unregister_netdevice(dev); | ||
508 | |||
509 | dev_put(dev); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | /* Destroy an unresolved cache entry, killing queued skbs | ||
514 | and reporting error to netlink readers. | ||
515 | */ | ||
516 | |||
517 | static void ip6mr_destroy_unres(struct mfc6_cache *c) | ||
518 | { | ||
519 | struct sk_buff *skb; | ||
520 | |||
521 | atomic_dec(&cache_resolve_queue_len); | ||
522 | |||
523 | while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { | ||
524 | if (ipv6_hdr(skb)->version == 0) { | ||
525 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | ||
526 | nlh->nlmsg_type = NLMSG_ERROR; | ||
527 | nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); | ||
528 | skb_trim(skb, nlh->nlmsg_len); | ||
529 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT; | ||
530 | rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid); | ||
531 | } else | ||
532 | kfree_skb(skb); | ||
533 | } | ||
534 | |||
535 | kmem_cache_free(mrt_cachep, c); | ||
536 | } | ||
537 | |||
538 | |||
539 | /* Single timer process for all the unresolved queue. */ | ||
540 | |||
541 | static void ipmr_do_expire_process(unsigned long dummy) | ||
542 | { | ||
543 | unsigned long now = jiffies; | ||
544 | unsigned long expires = 10 * HZ; | ||
545 | struct mfc6_cache *c, **cp; | ||
546 | |||
547 | cp = &mfc_unres_queue; | ||
548 | |||
549 | while ((c = *cp) != NULL) { | ||
550 | if (time_after(c->mfc_un.unres.expires, now)) { | ||
551 | /* not yet... */ | ||
552 | unsigned long interval = c->mfc_un.unres.expires - now; | ||
553 | if (interval < expires) | ||
554 | expires = interval; | ||
555 | cp = &c->next; | ||
556 | continue; | ||
557 | } | ||
558 | |||
559 | *cp = c->next; | ||
560 | ip6mr_destroy_unres(c); | ||
561 | } | ||
562 | |||
563 | if (atomic_read(&cache_resolve_queue_len)) | ||
564 | mod_timer(&ipmr_expire_timer, jiffies + expires); | ||
565 | } | ||
566 | |||
567 | static void ipmr_expire_process(unsigned long dummy) | ||
568 | { | ||
569 | if (!spin_trylock(&mfc_unres_lock)) { | ||
570 | mod_timer(&ipmr_expire_timer, jiffies + 1); | ||
571 | return; | ||
572 | } | ||
573 | |||
574 | if (atomic_read(&cache_resolve_queue_len)) | ||
575 | ipmr_do_expire_process(dummy); | ||
576 | |||
577 | spin_unlock(&mfc_unres_lock); | ||
578 | } | ||
579 | |||
580 | /* Fill oifs list. It is called under write locked mrt_lock. */ | ||
581 | |||
582 | static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls) | ||
583 | { | ||
584 | int vifi; | ||
585 | |||
586 | cache->mfc_un.res.minvif = MAXMIFS; | ||
587 | cache->mfc_un.res.maxvif = 0; | ||
588 | memset(cache->mfc_un.res.ttls, 255, MAXMIFS); | ||
589 | |||
590 | for (vifi = 0; vifi < maxvif; vifi++) { | ||
591 | if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { | ||
592 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; | ||
593 | if (cache->mfc_un.res.minvif > vifi) | ||
594 | cache->mfc_un.res.minvif = vifi; | ||
595 | if (cache->mfc_un.res.maxvif <= vifi) | ||
596 | cache->mfc_un.res.maxvif = vifi + 1; | ||
597 | } | ||
598 | } | ||
599 | } | ||
600 | |||
601 | static int mif6_add(struct mif6ctl *vifc, int mrtsock) | ||
602 | { | ||
603 | int vifi = vifc->mif6c_mifi; | ||
604 | struct mif_device *v = &vif6_table[vifi]; | ||
605 | struct net_device *dev; | ||
606 | |||
607 | /* Is vif busy ? */ | ||
608 | if (MIF_EXISTS(vifi)) | ||
609 | return -EADDRINUSE; | ||
610 | |||
611 | switch (vifc->mif6c_flags) { | ||
612 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
613 | case MIFF_REGISTER: | ||
614 | /* | ||
615 | * Special Purpose VIF in PIM | ||
616 | * All the packets will be sent to the daemon | ||
617 | */ | ||
618 | if (reg_vif_num >= 0) | ||
619 | return -EADDRINUSE; | ||
620 | dev = ip6mr_reg_vif(); | ||
621 | if (!dev) | ||
622 | return -ENOBUFS; | ||
623 | break; | ||
624 | #endif | ||
625 | case 0: | ||
626 | dev = dev_get_by_index(&init_net, vifc->mif6c_pifi); | ||
627 | if (!dev) | ||
628 | return -EADDRNOTAVAIL; | ||
629 | dev_put(dev); | ||
630 | break; | ||
631 | default: | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | dev_set_allmulti(dev, 1); | ||
636 | |||
637 | /* | ||
638 | * Fill in the VIF structures | ||
639 | */ | ||
640 | v->rate_limit = vifc->vifc_rate_limit; | ||
641 | v->flags = vifc->mif6c_flags; | ||
642 | if (!mrtsock) | ||
643 | v->flags |= VIFF_STATIC; | ||
644 | v->threshold = vifc->vifc_threshold; | ||
645 | v->bytes_in = 0; | ||
646 | v->bytes_out = 0; | ||
647 | v->pkt_in = 0; | ||
648 | v->pkt_out = 0; | ||
649 | v->link = dev->ifindex; | ||
650 | if (v->flags & MIFF_REGISTER) | ||
651 | v->link = dev->iflink; | ||
652 | |||
653 | /* And finish update writing critical data */ | ||
654 | write_lock_bh(&mrt_lock); | ||
655 | dev_hold(dev); | ||
656 | v->dev = dev; | ||
657 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
658 | if (v->flags & MIFF_REGISTER) | ||
659 | reg_vif_num = vifi; | ||
660 | #endif | ||
661 | if (vifi + 1 > maxvif) | ||
662 | maxvif = vifi + 1; | ||
663 | write_unlock_bh(&mrt_lock); | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_addr *mcastgrp) | ||
668 | { | ||
669 | int line = MFC6_HASH(mcastgrp, origin); | ||
670 | struct mfc6_cache *c; | ||
671 | |||
672 | for (c = mfc6_cache_array[line]; c; c = c->next) { | ||
673 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && | ||
674 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) | ||
675 | break; | ||
676 | } | ||
677 | return c; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * Allocate a multicast cache entry | ||
682 | */ | ||
683 | static struct mfc6_cache *ip6mr_cache_alloc(void) | ||
684 | { | ||
685 | struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_KERNEL); | ||
686 | if (c == NULL) | ||
687 | return NULL; | ||
688 | memset(c, 0, sizeof(*c)); | ||
689 | c->mfc_un.res.minvif = MAXMIFS; | ||
690 | return c; | ||
691 | } | ||
692 | |||
693 | static struct mfc6_cache *ip6mr_cache_alloc_unres(void) | ||
694 | { | ||
695 | struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_ATOMIC); | ||
696 | if (c == NULL) | ||
697 | return NULL; | ||
698 | memset(c, 0, sizeof(*c)); | ||
699 | skb_queue_head_init(&c->mfc_un.unres.unresolved); | ||
700 | c->mfc_un.unres.expires = jiffies + 10 * HZ; | ||
701 | return c; | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | * A cache entry has gone into a resolved state from queued | ||
706 | */ | ||
707 | |||
708 | static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | ||
709 | { | ||
710 | struct sk_buff *skb; | ||
711 | |||
712 | /* | ||
713 | * Play the pending entries through our router | ||
714 | */ | ||
715 | |||
716 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { | ||
717 | if (ipv6_hdr(skb)->version == 0) { | ||
718 | int err; | ||
719 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | ||
720 | |||
721 | if (ip6mr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) { | ||
722 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; | ||
723 | } else { | ||
724 | nlh->nlmsg_type = NLMSG_ERROR; | ||
725 | nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); | ||
726 | skb_trim(skb, nlh->nlmsg_len); | ||
727 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | ||
728 | } | ||
729 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid); | ||
730 | } else | ||
731 | ip6_mr_forward(skb, c); | ||
732 | } | ||
733 | } | ||
734 | |||
735 | /* | ||
736 | * Bounce a cache query up to pim6sd. We could use netlink for this but pim6sd | ||
737 | * expects the following bizarre scheme. | ||
738 | * | ||
739 | * Called under mrt_lock. | ||
740 | */ | ||
741 | |||
742 | static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert) | ||
743 | { | ||
744 | struct sk_buff *skb; | ||
745 | struct mrt6msg *msg; | ||
746 | int ret; | ||
747 | |||
748 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
749 | if (assert == MRT6MSG_WHOLEPKT) | ||
750 | skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt) | ||
751 | +sizeof(*msg)); | ||
752 | else | ||
753 | #endif | ||
754 | skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC); | ||
755 | |||
756 | if (!skb) | ||
757 | return -ENOBUFS; | ||
758 | |||
759 | /* I suppose that internal messages | ||
760 | * do not require checksums */ | ||
761 | |||
762 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
763 | |||
764 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
765 | if (assert == MRT6MSG_WHOLEPKT) { | ||
766 | /* Ugly, but we have no choice with this interface. | ||
767 | Duplicate old header, fix length etc. | ||
768 | And all this only to mangle msg->im6_msgtype and | ||
769 | to set msg->im6_mbz to "mbz" :-) | ||
770 | */ | ||
771 | skb_push(skb, -skb_network_offset(pkt)); | ||
772 | |||
773 | skb_push(skb, sizeof(*msg)); | ||
774 | skb_reset_transport_header(skb); | ||
775 | msg = (struct mrt6msg *)skb_transport_header(skb); | ||
776 | msg->im6_mbz = 0; | ||
777 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; | ||
778 | msg->im6_mif = reg_vif_num; | ||
779 | msg->im6_pad = 0; | ||
780 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | ||
781 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | ||
782 | |||
783 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
784 | } else | ||
785 | #endif | ||
786 | { | ||
787 | /* | ||
788 | * Copy the IP header | ||
789 | */ | ||
790 | |||
791 | skb_put(skb, sizeof(struct ipv6hdr)); | ||
792 | skb_reset_network_header(skb); | ||
793 | skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr)); | ||
794 | |||
795 | /* | ||
796 | * Add our header | ||
797 | */ | ||
798 | skb_put(skb, sizeof(*msg)); | ||
799 | skb_reset_transport_header(skb); | ||
800 | msg = (struct mrt6msg *)skb_transport_header(skb); | ||
801 | |||
802 | msg->im6_mbz = 0; | ||
803 | msg->im6_msgtype = assert; | ||
804 | msg->im6_mif = mifi; | ||
805 | msg->im6_pad = 0; | ||
806 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | ||
807 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | ||
808 | |||
809 | skb->dst = dst_clone(pkt->dst); | ||
810 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
811 | |||
812 | skb_pull(skb, sizeof(struct ipv6hdr)); | ||
813 | } | ||
814 | |||
815 | if (mroute6_socket == NULL) { | ||
816 | kfree_skb(skb); | ||
817 | return -EINVAL; | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * Deliver to user space multicast routing algorithms | ||
822 | */ | ||
823 | if ((ret = sock_queue_rcv_skb(mroute6_socket, skb)) < 0) { | ||
824 | if (net_ratelimit()) | ||
825 | printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n"); | ||
826 | kfree_skb(skb); | ||
827 | } | ||
828 | |||
829 | return ret; | ||
830 | } | ||
831 | |||
832 | /* | ||
833 | * Queue a packet for resolution. It gets locked cache entry! | ||
834 | */ | ||
835 | |||
836 | static int | ||
837 | ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb) | ||
838 | { | ||
839 | int err; | ||
840 | struct mfc6_cache *c; | ||
841 | |||
842 | spin_lock_bh(&mfc_unres_lock); | ||
843 | for (c = mfc_unres_queue; c; c = c->next) { | ||
844 | if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && | ||
845 | ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | if (c == NULL) { | ||
850 | /* | ||
851 | * Create a new entry if allowable | ||
852 | */ | ||
853 | |||
854 | if (atomic_read(&cache_resolve_queue_len) >= 10 || | ||
855 | (c = ip6mr_cache_alloc_unres()) == NULL) { | ||
856 | spin_unlock_bh(&mfc_unres_lock); | ||
857 | |||
858 | kfree_skb(skb); | ||
859 | return -ENOBUFS; | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * Fill in the new cache entry | ||
864 | */ | ||
865 | c->mf6c_parent = -1; | ||
866 | c->mf6c_origin = ipv6_hdr(skb)->saddr; | ||
867 | c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr; | ||
868 | |||
869 | /* | ||
870 | * Reflect first query at pim6sd | ||
871 | */ | ||
872 | if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) { | ||
873 | /* If the report failed throw the cache entry | ||
874 | out - Brad Parker | ||
875 | */ | ||
876 | spin_unlock_bh(&mfc_unres_lock); | ||
877 | |||
878 | kmem_cache_free(mrt_cachep, c); | ||
879 | kfree_skb(skb); | ||
880 | return err; | ||
881 | } | ||
882 | |||
883 | atomic_inc(&cache_resolve_queue_len); | ||
884 | c->next = mfc_unres_queue; | ||
885 | mfc_unres_queue = c; | ||
886 | |||
887 | ipmr_do_expire_process(1); | ||
888 | } | ||
889 | |||
890 | /* | ||
891 | * See if we can append the packet | ||
892 | */ | ||
893 | if (c->mfc_un.unres.unresolved.qlen > 3) { | ||
894 | kfree_skb(skb); | ||
895 | err = -ENOBUFS; | ||
896 | } else { | ||
897 | skb_queue_tail(&c->mfc_un.unres.unresolved, skb); | ||
898 | err = 0; | ||
899 | } | ||
900 | |||
901 | spin_unlock_bh(&mfc_unres_lock); | ||
902 | return err; | ||
903 | } | ||
904 | |||
905 | /* | ||
906 | * MFC6 cache manipulation by user space | ||
907 | */ | ||
908 | |||
909 | static int ip6mr_mfc_delete(struct mf6cctl *mfc) | ||
910 | { | ||
911 | int line; | ||
912 | struct mfc6_cache *c, **cp; | ||
913 | |||
914 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | ||
915 | |||
916 | for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { | ||
917 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | ||
918 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { | ||
919 | write_lock_bh(&mrt_lock); | ||
920 | *cp = c->next; | ||
921 | write_unlock_bh(&mrt_lock); | ||
922 | |||
923 | kmem_cache_free(mrt_cachep, c); | ||
924 | return 0; | ||
925 | } | ||
926 | } | ||
927 | return -ENOENT; | ||
928 | } | ||
929 | |||
930 | static int ip6mr_device_event(struct notifier_block *this, | ||
931 | unsigned long event, void *ptr) | ||
932 | { | ||
933 | struct net_device *dev = ptr; | ||
934 | struct mif_device *v; | ||
935 | int ct; | ||
936 | |||
937 | if (dev_net(dev) != &init_net) | ||
938 | return NOTIFY_DONE; | ||
939 | |||
940 | if (event != NETDEV_UNREGISTER) | ||
941 | return NOTIFY_DONE; | ||
942 | |||
943 | v = &vif6_table[0]; | ||
944 | for (ct = 0; ct < maxvif; ct++, v++) { | ||
945 | if (v->dev == dev) | ||
946 | mif6_delete(ct); | ||
947 | } | ||
948 | return NOTIFY_DONE; | ||
949 | } | ||
950 | |||
951 | static struct notifier_block ip6_mr_notifier = { | ||
952 | .notifier_call = ip6mr_device_event | ||
953 | }; | ||
954 | |||
955 | /* | ||
956 | * Setup for IP multicast routing | ||
957 | */ | ||
958 | |||
959 | void __init ip6_mr_init(void) | ||
960 | { | ||
961 | mrt_cachep = kmem_cache_create("ip6_mrt_cache", | ||
962 | sizeof(struct mfc6_cache), | ||
963 | 0, SLAB_HWCACHE_ALIGN, | ||
964 | NULL); | ||
965 | if (!mrt_cachep) | ||
966 | panic("cannot allocate ip6_mrt_cache"); | ||
967 | |||
968 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | ||
969 | register_netdevice_notifier(&ip6_mr_notifier); | ||
970 | #ifdef CONFIG_PROC_FS | ||
971 | proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops); | ||
972 | proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops); | ||
973 | #endif | ||
974 | } | ||
975 | |||
976 | |||
977 | static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) | ||
978 | { | ||
979 | int line; | ||
980 | struct mfc6_cache *uc, *c, **cp; | ||
981 | unsigned char ttls[MAXMIFS]; | ||
982 | int i; | ||
983 | |||
984 | memset(ttls, 255, MAXMIFS); | ||
985 | for (i = 0; i < MAXMIFS; i++) { | ||
986 | if (IF_ISSET(i, &mfc->mf6cc_ifset)) | ||
987 | ttls[i] = 1; | ||
988 | |||
989 | } | ||
990 | |||
991 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | ||
992 | |||
993 | for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { | ||
994 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | ||
995 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) | ||
996 | break; | ||
997 | } | ||
998 | |||
999 | if (c != NULL) { | ||
1000 | write_lock_bh(&mrt_lock); | ||
1001 | c->mf6c_parent = mfc->mf6cc_parent; | ||
1002 | ip6mr_update_thresholds(c, ttls); | ||
1003 | if (!mrtsock) | ||
1004 | c->mfc_flags |= MFC_STATIC; | ||
1005 | write_unlock_bh(&mrt_lock); | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) | ||
1010 | return -EINVAL; | ||
1011 | |||
1012 | c = ip6mr_cache_alloc(); | ||
1013 | if (c == NULL) | ||
1014 | return -ENOMEM; | ||
1015 | |||
1016 | c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; | ||
1017 | c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; | ||
1018 | c->mf6c_parent = mfc->mf6cc_parent; | ||
1019 | ip6mr_update_thresholds(c, ttls); | ||
1020 | if (!mrtsock) | ||
1021 | c->mfc_flags |= MFC_STATIC; | ||
1022 | |||
1023 | write_lock_bh(&mrt_lock); | ||
1024 | c->next = mfc6_cache_array[line]; | ||
1025 | mfc6_cache_array[line] = c; | ||
1026 | write_unlock_bh(&mrt_lock); | ||
1027 | |||
1028 | /* | ||
1029 | * Check to see if we resolved a queued list. If so we | ||
1030 | * need to send on the frames and tidy up. | ||
1031 | */ | ||
1032 | spin_lock_bh(&mfc_unres_lock); | ||
1033 | for (cp = &mfc_unres_queue; (uc = *cp) != NULL; | ||
1034 | cp = &uc->next) { | ||
1035 | if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && | ||
1036 | ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { | ||
1037 | *cp = uc->next; | ||
1038 | if (atomic_dec_and_test(&cache_resolve_queue_len)) | ||
1039 | del_timer(&ipmr_expire_timer); | ||
1040 | break; | ||
1041 | } | ||
1042 | } | ||
1043 | spin_unlock_bh(&mfc_unres_lock); | ||
1044 | |||
1045 | if (uc) { | ||
1046 | ip6mr_cache_resolve(uc, c); | ||
1047 | kmem_cache_free(mrt_cachep, uc); | ||
1048 | } | ||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | /* | ||
1053 | * Close the multicast socket, and clear the vif tables etc | ||
1054 | */ | ||
1055 | |||
1056 | static void mroute_clean_tables(struct sock *sk) | ||
1057 | { | ||
1058 | int i; | ||
1059 | |||
1060 | /* | ||
1061 | * Shut down all active vif entries | ||
1062 | */ | ||
1063 | for (i = 0; i < maxvif; i++) { | ||
1064 | if (!(vif6_table[i].flags & VIFF_STATIC)) | ||
1065 | mif6_delete(i); | ||
1066 | } | ||
1067 | |||
1068 | /* | ||
1069 | * Wipe the cache | ||
1070 | */ | ||
1071 | for (i = 0; i < ARRAY_SIZE(mfc6_cache_array); i++) { | ||
1072 | struct mfc6_cache *c, **cp; | ||
1073 | |||
1074 | cp = &mfc6_cache_array[i]; | ||
1075 | while ((c = *cp) != NULL) { | ||
1076 | if (c->mfc_flags & MFC_STATIC) { | ||
1077 | cp = &c->next; | ||
1078 | continue; | ||
1079 | } | ||
1080 | write_lock_bh(&mrt_lock); | ||
1081 | *cp = c->next; | ||
1082 | write_unlock_bh(&mrt_lock); | ||
1083 | |||
1084 | kmem_cache_free(mrt_cachep, c); | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | if (atomic_read(&cache_resolve_queue_len) != 0) { | ||
1089 | struct mfc6_cache *c; | ||
1090 | |||
1091 | spin_lock_bh(&mfc_unres_lock); | ||
1092 | while (mfc_unres_queue != NULL) { | ||
1093 | c = mfc_unres_queue; | ||
1094 | mfc_unres_queue = c->next; | ||
1095 | spin_unlock_bh(&mfc_unres_lock); | ||
1096 | |||
1097 | ip6mr_destroy_unres(c); | ||
1098 | |||
1099 | spin_lock_bh(&mfc_unres_lock); | ||
1100 | } | ||
1101 | spin_unlock_bh(&mfc_unres_lock); | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | static int ip6mr_sk_init(struct sock *sk) | ||
1106 | { | ||
1107 | int err = 0; | ||
1108 | |||
1109 | rtnl_lock(); | ||
1110 | write_lock_bh(&mrt_lock); | ||
1111 | if (likely(mroute6_socket == NULL)) | ||
1112 | mroute6_socket = sk; | ||
1113 | else | ||
1114 | err = -EADDRINUSE; | ||
1115 | write_unlock_bh(&mrt_lock); | ||
1116 | |||
1117 | rtnl_unlock(); | ||
1118 | |||
1119 | return err; | ||
1120 | } | ||
1121 | |||
1122 | int ip6mr_sk_done(struct sock *sk) | ||
1123 | { | ||
1124 | int err = 0; | ||
1125 | |||
1126 | rtnl_lock(); | ||
1127 | if (sk == mroute6_socket) { | ||
1128 | write_lock_bh(&mrt_lock); | ||
1129 | mroute6_socket = NULL; | ||
1130 | write_unlock_bh(&mrt_lock); | ||
1131 | |||
1132 | mroute_clean_tables(sk); | ||
1133 | } else | ||
1134 | err = -EACCES; | ||
1135 | rtnl_unlock(); | ||
1136 | |||
1137 | return err; | ||
1138 | } | ||
1139 | |||
1140 | /* | ||
1141 | * Socket options and virtual interface manipulation. The whole | ||
1142 | * virtual interface system is a complete heap, but unfortunately | ||
1143 | * that's how BSD mrouted happens to think. Maybe one day with a proper | ||
1144 | * MOSPF/PIM router set up we can clean this up. | ||
1145 | */ | ||
1146 | |||
1147 | int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen) | ||
1148 | { | ||
1149 | int ret; | ||
1150 | struct mif6ctl vif; | ||
1151 | struct mf6cctl mfc; | ||
1152 | mifi_t mifi; | ||
1153 | |||
1154 | if (optname != MRT6_INIT) { | ||
1155 | if (sk != mroute6_socket && !capable(CAP_NET_ADMIN)) | ||
1156 | return -EACCES; | ||
1157 | } | ||
1158 | |||
1159 | switch (optname) { | ||
1160 | case MRT6_INIT: | ||
1161 | if (sk->sk_type != SOCK_RAW || | ||
1162 | inet_sk(sk)->num != IPPROTO_ICMPV6) | ||
1163 | return -EOPNOTSUPP; | ||
1164 | if (optlen < sizeof(int)) | ||
1165 | return -EINVAL; | ||
1166 | |||
1167 | return ip6mr_sk_init(sk); | ||
1168 | |||
1169 | case MRT6_DONE: | ||
1170 | return ip6mr_sk_done(sk); | ||
1171 | |||
1172 | case MRT6_ADD_MIF: | ||
1173 | if (optlen < sizeof(vif)) | ||
1174 | return -EINVAL; | ||
1175 | if (copy_from_user(&vif, optval, sizeof(vif))) | ||
1176 | return -EFAULT; | ||
1177 | if (vif.mif6c_mifi >= MAXMIFS) | ||
1178 | return -ENFILE; | ||
1179 | rtnl_lock(); | ||
1180 | ret = mif6_add(&vif, sk == mroute6_socket); | ||
1181 | rtnl_unlock(); | ||
1182 | return ret; | ||
1183 | |||
1184 | case MRT6_DEL_MIF: | ||
1185 | if (optlen < sizeof(mifi_t)) | ||
1186 | return -EINVAL; | ||
1187 | if (copy_from_user(&mifi, optval, sizeof(mifi_t))) | ||
1188 | return -EFAULT; | ||
1189 | rtnl_lock(); | ||
1190 | ret = mif6_delete(mifi); | ||
1191 | rtnl_unlock(); | ||
1192 | return ret; | ||
1193 | |||
1194 | /* | ||
1195 | * Manipulate the forwarding caches. These live | ||
1196 | * in a sort of kernel/user symbiosis. | ||
1197 | */ | ||
1198 | case MRT6_ADD_MFC: | ||
1199 | case MRT6_DEL_MFC: | ||
1200 | if (optlen < sizeof(mfc)) | ||
1201 | return -EINVAL; | ||
1202 | if (copy_from_user(&mfc, optval, sizeof(mfc))) | ||
1203 | return -EFAULT; | ||
1204 | rtnl_lock(); | ||
1205 | if (optname == MRT6_DEL_MFC) | ||
1206 | ret = ip6mr_mfc_delete(&mfc); | ||
1207 | else | ||
1208 | ret = ip6mr_mfc_add(&mfc, sk == mroute6_socket); | ||
1209 | rtnl_unlock(); | ||
1210 | return ret; | ||
1211 | |||
1212 | /* | ||
1213 | * Control PIM assert (to activate pim will activate assert) | ||
1214 | */ | ||
1215 | case MRT6_ASSERT: | ||
1216 | { | ||
1217 | int v; | ||
1218 | if (get_user(v, (int __user *)optval)) | ||
1219 | return -EFAULT; | ||
1220 | mroute_do_assert = !!v; | ||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
1225 | case MRT6_PIM: | ||
1226 | { | ||
1227 | int v; | ||
1228 | if (get_user(v, (int __user *)optval)) | ||
1229 | return -EFAULT; | ||
1230 | v = !!v; | ||
1231 | rtnl_lock(); | ||
1232 | ret = 0; | ||
1233 | if (v != mroute_do_pim) { | ||
1234 | mroute_do_pim = v; | ||
1235 | mroute_do_assert = v; | ||
1236 | if (mroute_do_pim) | ||
1237 | ret = inet6_add_protocol(&pim6_protocol, | ||
1238 | IPPROTO_PIM); | ||
1239 | else | ||
1240 | ret = inet6_del_protocol(&pim6_protocol, | ||
1241 | IPPROTO_PIM); | ||
1242 | if (ret < 0) | ||
1243 | ret = -EAGAIN; | ||
1244 | } | ||
1245 | rtnl_unlock(); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | #endif | ||
1250 | /* | ||
1251 | * Spurious command, or MRT_VERSION which you cannot | ||
1252 | * set. | ||
1253 | */ | ||
1254 | default: | ||
1255 | return -ENOPROTOOPT; | ||
1256 | } | ||
1257 | } | ||
1258 | |||
1259 | /* | ||
1260 | * Getsock opt support for the multicast routing system. | ||
1261 | */ | ||
1262 | |||
1263 | int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, | ||
1264 | int __user *optlen) | ||
1265 | { | ||
1266 | int olr; | ||
1267 | int val; | ||
1268 | |||
1269 | switch (optname) { | ||
1270 | case MRT6_VERSION: | ||
1271 | val = 0x0305; | ||
1272 | break; | ||
1273 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
1274 | case MRT6_PIM: | ||
1275 | val = mroute_do_pim; | ||
1276 | break; | ||
1277 | #endif | ||
1278 | case MRT6_ASSERT: | ||
1279 | val = mroute_do_assert; | ||
1280 | break; | ||
1281 | default: | ||
1282 | return -ENOPROTOOPT; | ||
1283 | } | ||
1284 | |||
1285 | if (get_user(olr, optlen)) | ||
1286 | return -EFAULT; | ||
1287 | |||
1288 | olr = min_t(int, olr, sizeof(int)); | ||
1289 | if (olr < 0) | ||
1290 | return -EINVAL; | ||
1291 | |||
1292 | if (put_user(olr, optlen)) | ||
1293 | return -EFAULT; | ||
1294 | if (copy_to_user(optval, &val, olr)) | ||
1295 | return -EFAULT; | ||
1296 | return 0; | ||
1297 | } | ||
1298 | |||
1299 | /* | ||
1300 | * The IP multicast ioctl support routines. | ||
1301 | */ | ||
1302 | |||
1303 | int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | ||
1304 | { | ||
1305 | struct sioc_sg_req6 sr; | ||
1306 | struct sioc_mif_req6 vr; | ||
1307 | struct mif_device *vif; | ||
1308 | struct mfc6_cache *c; | ||
1309 | |||
1310 | switch (cmd) { | ||
1311 | case SIOCGETMIFCNT_IN6: | ||
1312 | if (copy_from_user(&vr, arg, sizeof(vr))) | ||
1313 | return -EFAULT; | ||
1314 | if (vr.mifi >= maxvif) | ||
1315 | return -EINVAL; | ||
1316 | read_lock(&mrt_lock); | ||
1317 | vif = &vif6_table[vr.mifi]; | ||
1318 | if (MIF_EXISTS(vr.mifi)) { | ||
1319 | vr.icount = vif->pkt_in; | ||
1320 | vr.ocount = vif->pkt_out; | ||
1321 | vr.ibytes = vif->bytes_in; | ||
1322 | vr.obytes = vif->bytes_out; | ||
1323 | read_unlock(&mrt_lock); | ||
1324 | |||
1325 | if (copy_to_user(arg, &vr, sizeof(vr))) | ||
1326 | return -EFAULT; | ||
1327 | return 0; | ||
1328 | } | ||
1329 | read_unlock(&mrt_lock); | ||
1330 | return -EADDRNOTAVAIL; | ||
1331 | case SIOCGETSGCNT_IN6: | ||
1332 | if (copy_from_user(&sr, arg, sizeof(sr))) | ||
1333 | return -EFAULT; | ||
1334 | |||
1335 | read_lock(&mrt_lock); | ||
1336 | c = ip6mr_cache_find(&sr.src.sin6_addr, &sr.grp.sin6_addr); | ||
1337 | if (c) { | ||
1338 | sr.pktcnt = c->mfc_un.res.pkt; | ||
1339 | sr.bytecnt = c->mfc_un.res.bytes; | ||
1340 | sr.wrong_if = c->mfc_un.res.wrong_if; | ||
1341 | read_unlock(&mrt_lock); | ||
1342 | |||
1343 | if (copy_to_user(arg, &sr, sizeof(sr))) | ||
1344 | return -EFAULT; | ||
1345 | return 0; | ||
1346 | } | ||
1347 | read_unlock(&mrt_lock); | ||
1348 | return -EADDRNOTAVAIL; | ||
1349 | default: | ||
1350 | return -ENOIOCTLCMD; | ||
1351 | } | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | static inline int ip6mr_forward2_finish(struct sk_buff *skb) | ||
1356 | { | ||
1357 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTFORWDATAGRAMS); | ||
1358 | return dst_output(skb); | ||
1359 | } | ||
1360 | |||
1361 | /* | ||
1362 | * Processing handlers for ip6mr_forward | ||
1363 | */ | ||
1364 | |||
1365 | static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | ||
1366 | { | ||
1367 | struct ipv6hdr *ipv6h; | ||
1368 | struct mif_device *vif = &vif6_table[vifi]; | ||
1369 | struct net_device *dev; | ||
1370 | struct dst_entry *dst; | ||
1371 | struct flowi fl; | ||
1372 | |||
1373 | if (vif->dev == NULL) | ||
1374 | goto out_free; | ||
1375 | |||
1376 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
1377 | if (vif->flags & MIFF_REGISTER) { | ||
1378 | vif->pkt_out++; | ||
1379 | vif->bytes_out += skb->len; | ||
1380 | ((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len; | ||
1381 | ((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++; | ||
1382 | ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT); | ||
1383 | kfree_skb(skb); | ||
1384 | return 0; | ||
1385 | } | ||
1386 | #endif | ||
1387 | |||
1388 | ipv6h = ipv6_hdr(skb); | ||
1389 | |||
1390 | fl = (struct flowi) { | ||
1391 | .oif = vif->link, | ||
1392 | .nl_u = { .ip6_u = | ||
1393 | { .daddr = ipv6h->daddr, } | ||
1394 | } | ||
1395 | }; | ||
1396 | |||
1397 | dst = ip6_route_output(&init_net, NULL, &fl); | ||
1398 | if (!dst) | ||
1399 | goto out_free; | ||
1400 | |||
1401 | dst_release(skb->dst); | ||
1402 | skb->dst = dst; | ||
1403 | |||
1404 | /* | ||
1405 | * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally | ||
1406 | * not only before forwarding, but after forwarding on all output | ||
1407 | * interfaces. It is clear, if mrouter runs a multicasting | ||
1408 | * program, it should receive packets not depending to what interface | ||
1409 | * program is joined. | ||
1410 | * If we will not make it, the program will have to join on all | ||
1411 | * interfaces. On the other hand, multihoming host (or router, but | ||
1412 | * not mrouter) cannot join to more than one interface - it will | ||
1413 | * result in receiving multiple packets. | ||
1414 | */ | ||
1415 | dev = vif->dev; | ||
1416 | skb->dev = dev; | ||
1417 | vif->pkt_out++; | ||
1418 | vif->bytes_out += skb->len; | ||
1419 | |||
1420 | /* We are about to write */ | ||
1421 | /* XXX: extension headers? */ | ||
1422 | if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev))) | ||
1423 | goto out_free; | ||
1424 | |||
1425 | ipv6h = ipv6_hdr(skb); | ||
1426 | ipv6h->hop_limit--; | ||
1427 | |||
1428 | IP6CB(skb)->flags |= IP6SKB_FORWARDED; | ||
1429 | |||
1430 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dev, | ||
1431 | ip6mr_forward2_finish); | ||
1432 | |||
1433 | out_free: | ||
1434 | kfree_skb(skb); | ||
1435 | return 0; | ||
1436 | } | ||
1437 | |||
1438 | static int ip6mr_find_vif(struct net_device *dev) | ||
1439 | { | ||
1440 | int ct; | ||
1441 | for (ct = maxvif - 1; ct >= 0; ct--) { | ||
1442 | if (vif6_table[ct].dev == dev) | ||
1443 | break; | ||
1444 | } | ||
1445 | return ct; | ||
1446 | } | ||
1447 | |||
1448 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | ||
1449 | { | ||
1450 | int psend = -1; | ||
1451 | int vif, ct; | ||
1452 | |||
1453 | vif = cache->mf6c_parent; | ||
1454 | cache->mfc_un.res.pkt++; | ||
1455 | cache->mfc_un.res.bytes += skb->len; | ||
1456 | |||
1457 | /* | ||
1458 | * Wrong interface: drop packet and (maybe) send PIM assert. | ||
1459 | */ | ||
1460 | if (vif6_table[vif].dev != skb->dev) { | ||
1461 | int true_vifi; | ||
1462 | |||
1463 | cache->mfc_un.res.wrong_if++; | ||
1464 | true_vifi = ip6mr_find_vif(skb->dev); | ||
1465 | |||
1466 | if (true_vifi >= 0 && mroute_do_assert && | ||
1467 | /* pimsm uses asserts, when switching from RPT to SPT, | ||
1468 | so that we cannot check that packet arrived on an oif. | ||
1469 | It is bad, but otherwise we would need to move pretty | ||
1470 | large chunk of pimd to kernel. Ough... --ANK | ||
1471 | */ | ||
1472 | (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) && | ||
1473 | time_after(jiffies, | ||
1474 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { | ||
1475 | cache->mfc_un.res.last_assert = jiffies; | ||
1476 | ip6mr_cache_report(skb, true_vifi, MRT6MSG_WRONGMIF); | ||
1477 | } | ||
1478 | goto dont_forward; | ||
1479 | } | ||
1480 | |||
1481 | vif6_table[vif].pkt_in++; | ||
1482 | vif6_table[vif].bytes_in += skb->len; | ||
1483 | |||
1484 | /* | ||
1485 | * Forward the frame | ||
1486 | */ | ||
1487 | for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) { | ||
1488 | if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) { | ||
1489 | if (psend != -1) { | ||
1490 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | ||
1491 | if (skb2) | ||
1492 | ip6mr_forward2(skb2, cache, psend); | ||
1493 | } | ||
1494 | psend = ct; | ||
1495 | } | ||
1496 | } | ||
1497 | if (psend != -1) { | ||
1498 | ip6mr_forward2(skb, cache, psend); | ||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1502 | dont_forward: | ||
1503 | kfree_skb(skb); | ||
1504 | return 0; | ||
1505 | } | ||
1506 | |||
1507 | |||
1508 | /* | ||
1509 | * Multicast packets for forwarding arrive here | ||
1510 | */ | ||
1511 | |||
1512 | int ip6_mr_input(struct sk_buff *skb) | ||
1513 | { | ||
1514 | struct mfc6_cache *cache; | ||
1515 | |||
1516 | read_lock(&mrt_lock); | ||
1517 | cache = ip6mr_cache_find(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); | ||
1518 | |||
1519 | /* | ||
1520 | * No usable cache entry | ||
1521 | */ | ||
1522 | if (cache == NULL) { | ||
1523 | int vif; | ||
1524 | |||
1525 | vif = ip6mr_find_vif(skb->dev); | ||
1526 | if (vif >= 0) { | ||
1527 | int err = ip6mr_cache_unresolved(vif, skb); | ||
1528 | read_unlock(&mrt_lock); | ||
1529 | |||
1530 | return err; | ||
1531 | } | ||
1532 | read_unlock(&mrt_lock); | ||
1533 | kfree_skb(skb); | ||
1534 | return -ENODEV; | ||
1535 | } | ||
1536 | |||
1537 | ip6_mr_forward(skb, cache); | ||
1538 | |||
1539 | read_unlock(&mrt_lock); | ||
1540 | |||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | static int | ||
1546 | ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm) | ||
1547 | { | ||
1548 | int ct; | ||
1549 | struct rtnexthop *nhp; | ||
1550 | struct net_device *dev = vif6_table[c->mf6c_parent].dev; | ||
1551 | u8 *b = skb_tail_pointer(skb); | ||
1552 | struct rtattr *mp_head; | ||
1553 | |||
1554 | if (dev) | ||
1555 | RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); | ||
1556 | |||
1557 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); | ||
1558 | |||
1559 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { | ||
1560 | if (c->mfc_un.res.ttls[ct] < 255) { | ||
1561 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) | ||
1562 | goto rtattr_failure; | ||
1563 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | ||
1564 | nhp->rtnh_flags = 0; | ||
1565 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; | ||
1566 | nhp->rtnh_ifindex = vif6_table[ct].dev->ifindex; | ||
1567 | nhp->rtnh_len = sizeof(*nhp); | ||
1568 | } | ||
1569 | } | ||
1570 | mp_head->rta_type = RTA_MULTIPATH; | ||
1571 | mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head; | ||
1572 | rtm->rtm_type = RTN_MULTICAST; | ||
1573 | return 1; | ||
1574 | |||
1575 | rtattr_failure: | ||
1576 | nlmsg_trim(skb, b); | ||
1577 | return -EMSGSIZE; | ||
1578 | } | ||
1579 | |||
1580 | int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) | ||
1581 | { | ||
1582 | int err; | ||
1583 | struct mfc6_cache *cache; | ||
1584 | struct rt6_info *rt = (struct rt6_info *)skb->dst; | ||
1585 | |||
1586 | read_lock(&mrt_lock); | ||
1587 | cache = ip6mr_cache_find(&rt->rt6i_src.addr, &rt->rt6i_dst.addr); | ||
1588 | |||
1589 | if (!cache) { | ||
1590 | struct sk_buff *skb2; | ||
1591 | struct ipv6hdr *iph; | ||
1592 | struct net_device *dev; | ||
1593 | int vif; | ||
1594 | |||
1595 | if (nowait) { | ||
1596 | read_unlock(&mrt_lock); | ||
1597 | return -EAGAIN; | ||
1598 | } | ||
1599 | |||
1600 | dev = skb->dev; | ||
1601 | if (dev == NULL || (vif = ip6mr_find_vif(dev)) < 0) { | ||
1602 | read_unlock(&mrt_lock); | ||
1603 | return -ENODEV; | ||
1604 | } | ||
1605 | |||
1606 | /* really correct? */ | ||
1607 | skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC); | ||
1608 | if (!skb2) { | ||
1609 | read_unlock(&mrt_lock); | ||
1610 | return -ENOMEM; | ||
1611 | } | ||
1612 | |||
1613 | skb_reset_transport_header(skb2); | ||
1614 | |||
1615 | skb_put(skb2, sizeof(struct ipv6hdr)); | ||
1616 | skb_reset_network_header(skb2); | ||
1617 | |||
1618 | iph = ipv6_hdr(skb2); | ||
1619 | iph->version = 0; | ||
1620 | iph->priority = 0; | ||
1621 | iph->flow_lbl[0] = 0; | ||
1622 | iph->flow_lbl[1] = 0; | ||
1623 | iph->flow_lbl[2] = 0; | ||
1624 | iph->payload_len = 0; | ||
1625 | iph->nexthdr = IPPROTO_NONE; | ||
1626 | iph->hop_limit = 0; | ||
1627 | ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr); | ||
1628 | ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr); | ||
1629 | |||
1630 | err = ip6mr_cache_unresolved(vif, skb2); | ||
1631 | read_unlock(&mrt_lock); | ||
1632 | |||
1633 | return err; | ||
1634 | } | ||
1635 | |||
1636 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) | ||
1637 | cache->mfc_flags |= MFC_NOTIFY; | ||
1638 | |||
1639 | err = ip6mr_fill_mroute(skb, cache, rtm); | ||
1640 | read_unlock(&mrt_lock); | ||
1641 | return err; | ||
1642 | } | ||
1643 | |||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index bf2a686aa13d..06de9d0e1f6b 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * | 16 | * |
17 | * FIXME: Make the setsockopt code POSIX compliant: That is | 17 | * FIXME: Make the setsockopt code POSIX compliant: That is |
18 | * | 18 | * |
19 | * o Return -EINVAL for setsockopt of short lengths | ||
20 | * o Truncate getsockopt returns | 19 | * o Truncate getsockopt returns |
21 | * o Return an optlen of the truncated length if need be | 20 | * o Return an optlen of the truncated length if need be |
22 | * | 21 | * |
@@ -33,6 +32,7 @@ | |||
33 | #include <linux/sockios.h> | 32 | #include <linux/sockios.h> |
34 | #include <linux/net.h> | 33 | #include <linux/net.h> |
35 | #include <linux/in6.h> | 34 | #include <linux/in6.h> |
35 | #include <linux/mroute6.h> | ||
36 | #include <linux/netdevice.h> | 36 | #include <linux/netdevice.h> |
37 | #include <linux/if_arp.h> | 37 | #include <linux/if_arp.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
@@ -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 | ||
@@ -215,25 +103,59 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) | |||
215 | return 0; | 103 | return 0; |
216 | } | 104 | } |
217 | 105 | ||
106 | static | ||
107 | struct ipv6_txoptions *ipv6_update_options(struct sock *sk, | ||
108 | struct ipv6_txoptions *opt) | ||
109 | { | ||
110 | if (inet_sk(sk)->is_icsk) { | ||
111 | if (opt && | ||
112 | !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && | ||
113 | inet_sk(sk)->daddr != LOOPBACK4_IPV6) { | ||
114 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
115 | icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; | ||
116 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); | ||
117 | } | ||
118 | opt = xchg(&inet6_sk(sk)->opt, opt); | ||
119 | } else { | ||
120 | write_lock(&sk->sk_dst_lock); | ||
121 | opt = xchg(&inet6_sk(sk)->opt, opt); | ||
122 | write_unlock(&sk->sk_dst_lock); | ||
123 | } | ||
124 | sk_dst_reset(sk); | ||
125 | |||
126 | return opt; | ||
127 | } | ||
128 | |||
218 | static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | 129 | static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, |
219 | char __user *optval, int optlen) | 130 | char __user *optval, int optlen) |
220 | { | 131 | { |
221 | struct ipv6_pinfo *np = inet6_sk(sk); | 132 | struct ipv6_pinfo *np = inet6_sk(sk); |
133 | struct net *net = sock_net(sk); | ||
222 | int val, valbool; | 134 | int val, valbool; |
223 | int retv = -ENOPROTOOPT; | 135 | int retv = -ENOPROTOOPT; |
224 | 136 | ||
225 | if (optval == NULL) | 137 | if (optval == NULL) |
226 | val=0; | 138 | val=0; |
227 | else if (get_user(val, (int __user *) optval)) | 139 | else { |
228 | return -EFAULT; | 140 | if (optlen >= sizeof(int)) { |
141 | if (get_user(val, (int __user *) optval)) | ||
142 | return -EFAULT; | ||
143 | } else | ||
144 | val = 0; | ||
145 | } | ||
229 | 146 | ||
230 | valbool = (val!=0); | 147 | valbool = (val!=0); |
231 | 148 | ||
149 | if (ip6_mroute_opt(optname)) | ||
150 | return ip6_mroute_setsockopt(sk, optname, optval, optlen); | ||
151 | |||
232 | lock_sock(sk); | 152 | lock_sock(sk); |
233 | 153 | ||
234 | switch (optname) { | 154 | switch (optname) { |
235 | 155 | ||
236 | case IPV6_ADDRFORM: | 156 | case IPV6_ADDRFORM: |
157 | if (optlen < sizeof(int)) | ||
158 | goto e_inval; | ||
237 | if (val == PF_INET) { | 159 | if (val == PF_INET) { |
238 | struct ipv6_txoptions *opt; | 160 | struct ipv6_txoptions *opt; |
239 | struct sk_buff *pktopt; | 161 | struct sk_buff *pktopt; |
@@ -266,10 +188,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
266 | 188 | ||
267 | if (sk->sk_protocol == IPPROTO_TCP) { | 189 | if (sk->sk_protocol == IPPROTO_TCP) { |
268 | struct inet_connection_sock *icsk = inet_csk(sk); | 190 | struct inet_connection_sock *icsk = inet_csk(sk); |
269 | |||
270 | local_bh_disable(); | 191 | local_bh_disable(); |
271 | sock_prot_inuse_add(sk->sk_prot, -1); | 192 | sock_prot_inuse_add(net, sk->sk_prot, -1); |
272 | sock_prot_inuse_add(&tcp_prot, 1); | 193 | sock_prot_inuse_add(net, &tcp_prot, 1); |
273 | local_bh_enable(); | 194 | local_bh_enable(); |
274 | sk->sk_prot = &tcp_prot; | 195 | sk->sk_prot = &tcp_prot; |
275 | icsk->icsk_af_ops = &ipv4_specific; | 196 | icsk->icsk_af_ops = &ipv4_specific; |
@@ -282,8 +203,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
282 | if (sk->sk_protocol == IPPROTO_UDPLITE) | 203 | if (sk->sk_protocol == IPPROTO_UDPLITE) |
283 | prot = &udplite_prot; | 204 | prot = &udplite_prot; |
284 | local_bh_disable(); | 205 | local_bh_disable(); |
285 | sock_prot_inuse_add(sk->sk_prot, -1); | 206 | sock_prot_inuse_add(net, sk->sk_prot, -1); |
286 | sock_prot_inuse_add(prot, 1); | 207 | sock_prot_inuse_add(net, prot, 1); |
287 | local_bh_enable(); | 208 | local_bh_enable(); |
288 | sk->sk_prot = prot; | 209 | sk->sk_prot = prot; |
289 | sk->sk_socket->ops = &inet_dgram_ops; | 210 | sk->sk_socket->ops = &inet_dgram_ops; |
@@ -309,63 +230,86 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
309 | goto e_inval; | 230 | goto e_inval; |
310 | 231 | ||
311 | case IPV6_V6ONLY: | 232 | case IPV6_V6ONLY: |
312 | if (inet_sk(sk)->num) | 233 | if (optlen < sizeof(int) || |
234 | inet_sk(sk)->num) | ||
313 | goto e_inval; | 235 | goto e_inval; |
314 | np->ipv6only = valbool; | 236 | np->ipv6only = valbool; |
315 | retv = 0; | 237 | retv = 0; |
316 | break; | 238 | break; |
317 | 239 | ||
318 | case IPV6_RECVPKTINFO: | 240 | case IPV6_RECVPKTINFO: |
241 | if (optlen < sizeof(int)) | ||
242 | goto e_inval; | ||
319 | np->rxopt.bits.rxinfo = valbool; | 243 | np->rxopt.bits.rxinfo = valbool; |
320 | retv = 0; | 244 | retv = 0; |
321 | break; | 245 | break; |
322 | 246 | ||
323 | case IPV6_2292PKTINFO: | 247 | case IPV6_2292PKTINFO: |
248 | if (optlen < sizeof(int)) | ||
249 | goto e_inval; | ||
324 | np->rxopt.bits.rxoinfo = valbool; | 250 | np->rxopt.bits.rxoinfo = valbool; |
325 | retv = 0; | 251 | retv = 0; |
326 | break; | 252 | break; |
327 | 253 | ||
328 | case IPV6_RECVHOPLIMIT: | 254 | case IPV6_RECVHOPLIMIT: |
255 | if (optlen < sizeof(int)) | ||
256 | goto e_inval; | ||
329 | np->rxopt.bits.rxhlim = valbool; | 257 | np->rxopt.bits.rxhlim = valbool; |
330 | retv = 0; | 258 | retv = 0; |
331 | break; | 259 | break; |
332 | 260 | ||
333 | case IPV6_2292HOPLIMIT: | 261 | case IPV6_2292HOPLIMIT: |
262 | if (optlen < sizeof(int)) | ||
263 | goto e_inval; | ||
334 | np->rxopt.bits.rxohlim = valbool; | 264 | np->rxopt.bits.rxohlim = valbool; |
335 | retv = 0; | 265 | retv = 0; |
336 | break; | 266 | break; |
337 | 267 | ||
338 | case IPV6_RECVRTHDR: | 268 | case IPV6_RECVRTHDR: |
269 | if (optlen < sizeof(int)) | ||
270 | goto e_inval; | ||
339 | np->rxopt.bits.srcrt = valbool; | 271 | np->rxopt.bits.srcrt = valbool; |
340 | retv = 0; | 272 | retv = 0; |
341 | break; | 273 | break; |
342 | 274 | ||
343 | case IPV6_2292RTHDR: | 275 | case IPV6_2292RTHDR: |
276 | if (optlen < sizeof(int)) | ||
277 | goto e_inval; | ||
344 | np->rxopt.bits.osrcrt = valbool; | 278 | np->rxopt.bits.osrcrt = valbool; |
345 | retv = 0; | 279 | retv = 0; |
346 | break; | 280 | break; |
347 | 281 | ||
348 | case IPV6_RECVHOPOPTS: | 282 | case IPV6_RECVHOPOPTS: |
283 | if (optlen < sizeof(int)) | ||
284 | goto e_inval; | ||
349 | np->rxopt.bits.hopopts = valbool; | 285 | np->rxopt.bits.hopopts = valbool; |
350 | retv = 0; | 286 | retv = 0; |
351 | break; | 287 | break; |
352 | 288 | ||
353 | case IPV6_2292HOPOPTS: | 289 | case IPV6_2292HOPOPTS: |
290 | if (optlen < sizeof(int)) | ||
291 | goto e_inval; | ||
354 | np->rxopt.bits.ohopopts = valbool; | 292 | np->rxopt.bits.ohopopts = valbool; |
355 | retv = 0; | 293 | retv = 0; |
356 | break; | 294 | break; |
357 | 295 | ||
358 | case IPV6_RECVDSTOPTS: | 296 | case IPV6_RECVDSTOPTS: |
297 | if (optlen < sizeof(int)) | ||
298 | goto e_inval; | ||
359 | np->rxopt.bits.dstopts = valbool; | 299 | np->rxopt.bits.dstopts = valbool; |
360 | retv = 0; | 300 | retv = 0; |
361 | break; | 301 | break; |
362 | 302 | ||
363 | case IPV6_2292DSTOPTS: | 303 | case IPV6_2292DSTOPTS: |
304 | if (optlen < sizeof(int)) | ||
305 | goto e_inval; | ||
364 | np->rxopt.bits.odstopts = valbool; | 306 | np->rxopt.bits.odstopts = valbool; |
365 | retv = 0; | 307 | retv = 0; |
366 | break; | 308 | break; |
367 | 309 | ||
368 | case IPV6_TCLASS: | 310 | case IPV6_TCLASS: |
311 | if (optlen < sizeof(int)) | ||
312 | goto e_inval; | ||
369 | if (val < -1 || val > 0xff) | 313 | if (val < -1 || val > 0xff) |
370 | goto e_inval; | 314 | goto e_inval; |
371 | np->tclass = val; | 315 | np->tclass = val; |
@@ -373,11 +317,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
373 | break; | 317 | break; |
374 | 318 | ||
375 | case IPV6_RECVTCLASS: | 319 | case IPV6_RECVTCLASS: |
320 | if (optlen < sizeof(int)) | ||
321 | goto e_inval; | ||
376 | np->rxopt.bits.rxtclass = valbool; | 322 | np->rxopt.bits.rxtclass = valbool; |
377 | retv = 0; | 323 | retv = 0; |
378 | break; | 324 | break; |
379 | 325 | ||
380 | case IPV6_FLOWINFO: | 326 | case IPV6_FLOWINFO: |
327 | if (optlen < sizeof(int)) | ||
328 | goto e_inval; | ||
381 | np->rxopt.bits.rxflow = valbool; | 329 | np->rxopt.bits.rxflow = valbool; |
382 | retv = 0; | 330 | retv = 0; |
383 | break; | 331 | break; |
@@ -396,9 +344,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
396 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 344 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
397 | break; | 345 | break; |
398 | 346 | ||
399 | retv = -EINVAL; | 347 | if (optlen < sizeof(struct ipv6_opt_hdr) || |
400 | if (optlen & 0x7 || optlen > 8 * 255) | 348 | optlen & 0x7 || optlen > 8 * 255) |
401 | break; | 349 | goto e_inval; |
402 | 350 | ||
403 | opt = ipv6_renew_options(sk, np->opt, optname, | 351 | opt = ipv6_renew_options(sk, np->opt, optname, |
404 | (struct ipv6_opt_hdr __user *)optval, | 352 | (struct ipv6_opt_hdr __user *)optval, |
@@ -426,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
426 | } | 374 | } |
427 | 375 | ||
428 | retv = 0; | 376 | retv = 0; |
429 | if (inet_sk(sk)->is_icsk) { | 377 | opt = ipv6_update_options(sk, opt); |
430 | if (opt) { | ||
431 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
432 | if (!((1 << sk->sk_state) & | ||
433 | (TCPF_LISTEN | TCPF_CLOSE)) | ||
434 | && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { | ||
435 | icsk->icsk_ext_hdr_len = | ||
436 | opt->opt_flen + opt->opt_nflen; | ||
437 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); | ||
438 | } | ||
439 | } | ||
440 | opt = xchg(&np->opt, opt); | ||
441 | sk_dst_reset(sk); | ||
442 | } else { | ||
443 | write_lock(&sk->sk_dst_lock); | ||
444 | opt = xchg(&np->opt, opt); | ||
445 | write_unlock(&sk->sk_dst_lock); | ||
446 | sk_dst_reset(sk); | ||
447 | } | ||
448 | sticky_done: | 378 | sticky_done: |
449 | if (opt) | 379 | if (opt) |
450 | sock_kfree_s(sk, opt, opt->tot_len); | 380 | sock_kfree_s(sk, opt, opt->tot_len); |
@@ -490,32 +420,15 @@ sticky_done: | |||
490 | goto done; | 420 | goto done; |
491 | update: | 421 | update: |
492 | retv = 0; | 422 | retv = 0; |
493 | if (inet_sk(sk)->is_icsk) { | 423 | opt = ipv6_update_options(sk, opt); |
494 | if (opt) { | ||
495 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
496 | if (!((1 << sk->sk_state) & | ||
497 | (TCPF_LISTEN | TCPF_CLOSE)) | ||
498 | && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { | ||
499 | icsk->icsk_ext_hdr_len = | ||
500 | opt->opt_flen + opt->opt_nflen; | ||
501 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); | ||
502 | } | ||
503 | } | ||
504 | opt = xchg(&np->opt, opt); | ||
505 | sk_dst_reset(sk); | ||
506 | } else { | ||
507 | write_lock(&sk->sk_dst_lock); | ||
508 | opt = xchg(&np->opt, opt); | ||
509 | write_unlock(&sk->sk_dst_lock); | ||
510 | sk_dst_reset(sk); | ||
511 | } | ||
512 | |||
513 | done: | 424 | done: |
514 | if (opt) | 425 | if (opt) |
515 | sock_kfree_s(sk, opt, opt->tot_len); | 426 | sock_kfree_s(sk, opt, opt->tot_len); |
516 | break; | 427 | break; |
517 | } | 428 | } |
518 | case IPV6_UNICAST_HOPS: | 429 | case IPV6_UNICAST_HOPS: |
430 | if (optlen < sizeof(int)) | ||
431 | goto e_inval; | ||
519 | if (val > 255 || val < -1) | 432 | if (val > 255 || val < -1) |
520 | goto e_inval; | 433 | goto e_inval; |
521 | np->hop_limit = val; | 434 | np->hop_limit = val; |
@@ -525,6 +438,8 @@ done: | |||
525 | case IPV6_MULTICAST_HOPS: | 438 | case IPV6_MULTICAST_HOPS: |
526 | if (sk->sk_type == SOCK_STREAM) | 439 | if (sk->sk_type == SOCK_STREAM) |
527 | goto e_inval; | 440 | goto e_inval; |
441 | if (optlen < sizeof(int)) | ||
442 | goto e_inval; | ||
528 | if (val > 255 || val < -1) | 443 | if (val > 255 || val < -1) |
529 | goto e_inval; | 444 | goto e_inval; |
530 | np->mcast_hops = val; | 445 | np->mcast_hops = val; |
@@ -532,6 +447,8 @@ done: | |||
532 | break; | 447 | break; |
533 | 448 | ||
534 | case IPV6_MULTICAST_LOOP: | 449 | case IPV6_MULTICAST_LOOP: |
450 | if (optlen < sizeof(int)) | ||
451 | goto e_inval; | ||
535 | np->mc_loop = valbool; | 452 | np->mc_loop = valbool; |
536 | retv = 0; | 453 | retv = 0; |
537 | break; | 454 | break; |
@@ -539,12 +456,14 @@ done: | |||
539 | case IPV6_MULTICAST_IF: | 456 | case IPV6_MULTICAST_IF: |
540 | if (sk->sk_type == SOCK_STREAM) | 457 | if (sk->sk_type == SOCK_STREAM) |
541 | goto e_inval; | 458 | goto e_inval; |
459 | if (optlen < sizeof(int)) | ||
460 | goto e_inval; | ||
542 | 461 | ||
543 | if (val) { | 462 | if (val) { |
544 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) | 463 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) |
545 | goto e_inval; | 464 | goto e_inval; |
546 | 465 | ||
547 | if (__dev_get_by_index(&init_net, val) == NULL) { | 466 | if (__dev_get_by_index(net, val) == NULL) { |
548 | retv = -ENODEV; | 467 | retv = -ENODEV; |
549 | break; | 468 | break; |
550 | } | 469 | } |
@@ -557,6 +476,9 @@ done: | |||
557 | { | 476 | { |
558 | struct ipv6_mreq mreq; | 477 | struct ipv6_mreq mreq; |
559 | 478 | ||
479 | if (optlen < sizeof(struct ipv6_mreq)) | ||
480 | goto e_inval; | ||
481 | |||
560 | retv = -EPROTO; | 482 | retv = -EPROTO; |
561 | if (inet_sk(sk)->is_icsk) | 483 | if (inet_sk(sk)->is_icsk) |
562 | break; | 484 | break; |
@@ -576,7 +498,7 @@ done: | |||
576 | { | 498 | { |
577 | struct ipv6_mreq mreq; | 499 | struct ipv6_mreq mreq; |
578 | 500 | ||
579 | if (optlen != sizeof(struct ipv6_mreq)) | 501 | if (optlen < sizeof(struct ipv6_mreq)) |
580 | goto e_inval; | 502 | goto e_inval; |
581 | 503 | ||
582 | retv = -EFAULT; | 504 | retv = -EFAULT; |
@@ -595,6 +517,9 @@ done: | |||
595 | struct group_req greq; | 517 | struct group_req greq; |
596 | struct sockaddr_in6 *psin6; | 518 | struct sockaddr_in6 *psin6; |
597 | 519 | ||
520 | if (optlen < sizeof(struct group_req)) | ||
521 | goto e_inval; | ||
522 | |||
598 | retv = -EFAULT; | 523 | retv = -EFAULT; |
599 | if (copy_from_user(&greq, optval, sizeof(struct group_req))) | 524 | if (copy_from_user(&greq, optval, sizeof(struct group_req))) |
600 | break; | 525 | break; |
@@ -619,7 +544,7 @@ done: | |||
619 | struct group_source_req greqs; | 544 | struct group_source_req greqs; |
620 | int omode, add; | 545 | int omode, add; |
621 | 546 | ||
622 | if (optlen != sizeof(struct group_source_req)) | 547 | if (optlen < sizeof(struct group_source_req)) |
623 | goto e_inval; | 548 | goto e_inval; |
624 | if (copy_from_user(&greqs, optval, sizeof(greqs))) { | 549 | if (copy_from_user(&greqs, optval, sizeof(greqs))) { |
625 | retv = -EFAULT; | 550 | retv = -EFAULT; |
@@ -693,27 +618,37 @@ done: | |||
693 | break; | 618 | break; |
694 | } | 619 | } |
695 | case IPV6_ROUTER_ALERT: | 620 | case IPV6_ROUTER_ALERT: |
621 | if (optlen < sizeof(int)) | ||
622 | goto e_inval; | ||
696 | retv = ip6_ra_control(sk, val, NULL); | 623 | retv = ip6_ra_control(sk, val, NULL); |
697 | break; | 624 | break; |
698 | case IPV6_MTU_DISCOVER: | 625 | case IPV6_MTU_DISCOVER: |
626 | if (optlen < sizeof(int)) | ||
627 | goto e_inval; | ||
699 | if (val<0 || val>3) | 628 | if (val<0 || val>3) |
700 | goto e_inval; | 629 | goto e_inval; |
701 | np->pmtudisc = val; | 630 | np->pmtudisc = val; |
702 | retv = 0; | 631 | retv = 0; |
703 | break; | 632 | break; |
704 | case IPV6_MTU: | 633 | case IPV6_MTU: |
634 | if (optlen < sizeof(int)) | ||
635 | goto e_inval; | ||
705 | if (val && val < IPV6_MIN_MTU) | 636 | if (val && val < IPV6_MIN_MTU) |
706 | goto e_inval; | 637 | goto e_inval; |
707 | np->frag_size = val; | 638 | np->frag_size = val; |
708 | retv = 0; | 639 | retv = 0; |
709 | break; | 640 | break; |
710 | case IPV6_RECVERR: | 641 | case IPV6_RECVERR: |
642 | if (optlen < sizeof(int)) | ||
643 | goto e_inval; | ||
711 | np->recverr = valbool; | 644 | np->recverr = valbool; |
712 | if (!val) | 645 | if (!val) |
713 | skb_queue_purge(&sk->sk_error_queue); | 646 | skb_queue_purge(&sk->sk_error_queue); |
714 | retv = 0; | 647 | retv = 0; |
715 | break; | 648 | break; |
716 | case IPV6_FLOWINFO_SEND: | 649 | case IPV6_FLOWINFO_SEND: |
650 | if (optlen < sizeof(int)) | ||
651 | goto e_inval; | ||
717 | np->sndflow = valbool; | 652 | np->sndflow = valbool; |
718 | retv = 0; | 653 | retv = 0; |
719 | break; | 654 | break; |
@@ -728,7 +663,70 @@ done: | |||
728 | retv = xfrm_user_policy(sk, optname, optval, optlen); | 663 | retv = xfrm_user_policy(sk, optname, optval, optlen); |
729 | break; | 664 | break; |
730 | 665 | ||
666 | case IPV6_ADDR_PREFERENCES: | ||
667 | { | ||
668 | unsigned int pref = 0; | ||
669 | unsigned int prefmask = ~0; | ||
670 | |||
671 | if (optlen < sizeof(int)) | ||
672 | goto e_inval; | ||
673 | |||
674 | retv = -EINVAL; | ||
675 | |||
676 | /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ | ||
677 | switch (val & (IPV6_PREFER_SRC_PUBLIC| | ||
678 | IPV6_PREFER_SRC_TMP| | ||
679 | IPV6_PREFER_SRC_PUBTMP_DEFAULT)) { | ||
680 | case IPV6_PREFER_SRC_PUBLIC: | ||
681 | pref |= IPV6_PREFER_SRC_PUBLIC; | ||
682 | break; | ||
683 | case IPV6_PREFER_SRC_TMP: | ||
684 | pref |= IPV6_PREFER_SRC_TMP; | ||
685 | break; | ||
686 | case IPV6_PREFER_SRC_PUBTMP_DEFAULT: | ||
687 | break; | ||
688 | case 0: | ||
689 | goto pref_skip_pubtmp; | ||
690 | default: | ||
691 | goto e_inval; | ||
692 | } | ||
693 | |||
694 | prefmask &= ~(IPV6_PREFER_SRC_PUBLIC| | ||
695 | IPV6_PREFER_SRC_TMP); | ||
696 | pref_skip_pubtmp: | ||
697 | |||
698 | /* check HOME/COA conflicts */ | ||
699 | switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) { | ||
700 | case IPV6_PREFER_SRC_HOME: | ||
701 | break; | ||
702 | case IPV6_PREFER_SRC_COA: | ||
703 | pref |= IPV6_PREFER_SRC_COA; | ||
704 | case 0: | ||
705 | goto pref_skip_coa; | ||
706 | default: | ||
707 | goto e_inval; | ||
708 | } | ||
709 | |||
710 | prefmask &= ~IPV6_PREFER_SRC_COA; | ||
711 | pref_skip_coa: | ||
712 | |||
713 | /* check CGA/NONCGA conflicts */ | ||
714 | switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) { | ||
715 | case IPV6_PREFER_SRC_CGA: | ||
716 | case IPV6_PREFER_SRC_NONCGA: | ||
717 | case 0: | ||
718 | break; | ||
719 | default: | ||
720 | goto e_inval; | ||
721 | } | ||
722 | |||
723 | np->srcprefs = (np->srcprefs & prefmask) | pref; | ||
724 | retv = 0; | ||
725 | |||
726 | break; | ||
727 | } | ||
731 | } | 728 | } |
729 | |||
732 | release_sock(sk); | 730 | release_sock(sk); |
733 | 731 | ||
734 | return retv; | 732 | return retv; |
@@ -839,6 +837,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
839 | int len; | 837 | int len; |
840 | int val; | 838 | int val; |
841 | 839 | ||
840 | if (ip6_mroute_opt(optname)) | ||
841 | return ip6_mroute_getsockopt(sk, optname, optval, optlen); | ||
842 | |||
842 | if (get_user(len, optlen)) | 843 | if (get_user(len, optlen)) |
843 | return -EFAULT; | 844 | return -EFAULT; |
844 | switch (optname) { | 845 | switch (optname) { |
@@ -1015,9 +1016,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1015 | dst = sk_dst_get(sk); | 1016 | dst = sk_dst_get(sk); |
1016 | if (dst) { | 1017 | if (dst) { |
1017 | if (val < 0) | 1018 | if (val < 0) |
1018 | val = dst_metric(dst, RTAX_HOPLIMIT); | 1019 | val = ip6_dst_hoplimit(dst); |
1019 | if (val < 0) | ||
1020 | val = ipv6_get_hoplimit(dst->dev); | ||
1021 | dst_release(dst); | 1020 | dst_release(dst); |
1022 | } | 1021 | } |
1023 | if (val < 0) | 1022 | if (val < 0) |
@@ -1045,6 +1044,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1045 | val = np->sndflow; | 1044 | val = np->sndflow; |
1046 | break; | 1045 | break; |
1047 | 1046 | ||
1047 | case IPV6_ADDR_PREFERENCES: | ||
1048 | val = 0; | ||
1049 | |||
1050 | if (np->srcprefs & IPV6_PREFER_SRC_TMP) | ||
1051 | val |= IPV6_PREFER_SRC_TMP; | ||
1052 | else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC) | ||
1053 | val |= IPV6_PREFER_SRC_PUBLIC; | ||
1054 | else { | ||
1055 | /* XXX: should we return system default? */ | ||
1056 | val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT; | ||
1057 | } | ||
1058 | |||
1059 | if (np->srcprefs & IPV6_PREFER_SRC_COA) | ||
1060 | val |= IPV6_PREFER_SRC_COA; | ||
1061 | else | ||
1062 | val |= IPV6_PREFER_SRC_HOME; | ||
1063 | break; | ||
1064 | |||
1048 | default: | 1065 | default: |
1049 | return -ENOPROTOOPT; | 1066 | return -ENOPROTOOPT; |
1050 | } | 1067 | } |
@@ -1128,13 +1145,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1128 | EXPORT_SYMBOL(compat_ipv6_getsockopt); | 1145 | EXPORT_SYMBOL(compat_ipv6_getsockopt); |
1129 | #endif | 1146 | #endif |
1130 | 1147 | ||
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..54f91efdae58 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <net/ndisc.h> | 59 | #include <net/ndisc.h> |
60 | #include <net/addrconf.h> | 60 | #include <net/addrconf.h> |
61 | #include <net/ip6_route.h> | 61 | #include <net/ip6_route.h> |
62 | #include <net/inet_common.h> | ||
62 | 63 | ||
63 | #include <net/ip6_checksum.h> | 64 | #include <net/ip6_checksum.h> |
64 | 65 | ||
@@ -126,10 +127,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | |||
126 | /* Big mc list lock for all the sockets */ | 127 | /* Big mc list lock for all the sockets */ |
127 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); | 128 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); |
128 | 129 | ||
129 | static struct socket *igmp6_socket; | ||
130 | |||
131 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); | ||
132 | |||
133 | static void igmp6_join_group(struct ifmcaddr6 *ma); | 130 | static void igmp6_join_group(struct ifmcaddr6 *ma); |
134 | static void igmp6_leave_group(struct ifmcaddr6 *ma); | 131 | static void igmp6_leave_group(struct ifmcaddr6 *ma); |
135 | static void igmp6_timer_handler(unsigned long data); | 132 | static void igmp6_timer_handler(unsigned long data); |
@@ -178,11 +175,12 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; | |||
178 | * socket join on multicast group | 175 | * socket join on multicast group |
179 | */ | 176 | */ |
180 | 177 | ||
181 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | 178 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) |
182 | { | 179 | { |
183 | struct net_device *dev = NULL; | 180 | struct net_device *dev = NULL; |
184 | struct ipv6_mc_socklist *mc_lst; | 181 | struct ipv6_mc_socklist *mc_lst; |
185 | struct ipv6_pinfo *np = inet6_sk(sk); | 182 | struct ipv6_pinfo *np = inet6_sk(sk); |
183 | struct net *net = sock_net(sk); | ||
186 | int err; | 184 | int err; |
187 | 185 | ||
188 | if (!ipv6_addr_is_multicast(addr)) | 186 | if (!ipv6_addr_is_multicast(addr)) |
@@ -208,14 +206,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
208 | 206 | ||
209 | if (ifindex == 0) { | 207 | if (ifindex == 0) { |
210 | struct rt6_info *rt; | 208 | struct rt6_info *rt; |
211 | rt = rt6_lookup(addr, NULL, 0, 0); | 209 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
212 | if (rt) { | 210 | if (rt) { |
213 | dev = rt->rt6i_dev; | 211 | dev = rt->rt6i_dev; |
214 | dev_hold(dev); | 212 | dev_hold(dev); |
215 | dst_release(&rt->u.dst); | 213 | dst_release(&rt->u.dst); |
216 | } | 214 | } |
217 | } else | 215 | } else |
218 | dev = dev_get_by_index(&init_net, ifindex); | 216 | dev = dev_get_by_index(net, ifindex); |
219 | 217 | ||
220 | if (dev == NULL) { | 218 | if (dev == NULL) { |
221 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 219 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
@@ -252,10 +250,11 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
252 | /* | 250 | /* |
253 | * socket leave on multicast group | 251 | * socket leave on multicast group |
254 | */ | 252 | */ |
255 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | 253 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) |
256 | { | 254 | { |
257 | struct ipv6_pinfo *np = inet6_sk(sk); | 255 | struct ipv6_pinfo *np = inet6_sk(sk); |
258 | struct ipv6_mc_socklist *mc_lst, **lnk; | 256 | struct ipv6_mc_socklist *mc_lst, **lnk; |
257 | struct net *net = sock_net(sk); | ||
259 | 258 | ||
260 | write_lock_bh(&ipv6_sk_mc_lock); | 259 | write_lock_bh(&ipv6_sk_mc_lock); |
261 | for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { | 260 | for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { |
@@ -266,7 +265,8 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
266 | *lnk = mc_lst->next; | 265 | *lnk = mc_lst->next; |
267 | write_unlock_bh(&ipv6_sk_mc_lock); | 266 | write_unlock_bh(&ipv6_sk_mc_lock); |
268 | 267 | ||
269 | if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) { | 268 | dev = dev_get_by_index(net, mc_lst->ifindex); |
269 | if (dev != NULL) { | ||
270 | struct inet6_dev *idev = in6_dev_get(dev); | 270 | struct inet6_dev *idev = in6_dev_get(dev); |
271 | 271 | ||
272 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | 272 | (void) ip6_mc_leave_src(sk, mc_lst, idev); |
@@ -286,7 +286,9 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
286 | return -EADDRNOTAVAIL; | 286 | return -EADDRNOTAVAIL; |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex) | 289 | static struct inet6_dev *ip6_mc_find_dev(struct net *net, |
290 | struct in6_addr *group, | ||
291 | int ifindex) | ||
290 | { | 292 | { |
291 | struct net_device *dev = NULL; | 293 | struct net_device *dev = NULL; |
292 | struct inet6_dev *idev = NULL; | 294 | struct inet6_dev *idev = NULL; |
@@ -294,14 +296,14 @@ static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex) | |||
294 | if (ifindex == 0) { | 296 | if (ifindex == 0) { |
295 | struct rt6_info *rt; | 297 | struct rt6_info *rt; |
296 | 298 | ||
297 | rt = rt6_lookup(group, NULL, 0, 0); | 299 | rt = rt6_lookup(net, group, NULL, 0, 0); |
298 | if (rt) { | 300 | if (rt) { |
299 | dev = rt->rt6i_dev; | 301 | dev = rt->rt6i_dev; |
300 | dev_hold(dev); | 302 | dev_hold(dev); |
301 | dst_release(&rt->u.dst); | 303 | dst_release(&rt->u.dst); |
302 | } | 304 | } |
303 | } else | 305 | } else |
304 | dev = dev_get_by_index(&init_net, ifindex); | 306 | dev = dev_get_by_index(net, ifindex); |
305 | 307 | ||
306 | if (!dev) | 308 | if (!dev) |
307 | return NULL; | 309 | return NULL; |
@@ -324,6 +326,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
324 | { | 326 | { |
325 | struct ipv6_pinfo *np = inet6_sk(sk); | 327 | struct ipv6_pinfo *np = inet6_sk(sk); |
326 | struct ipv6_mc_socklist *mc_lst; | 328 | struct ipv6_mc_socklist *mc_lst; |
329 | struct net *net = sock_net(sk); | ||
327 | 330 | ||
328 | write_lock_bh(&ipv6_sk_mc_lock); | 331 | write_lock_bh(&ipv6_sk_mc_lock); |
329 | while ((mc_lst = np->ipv6_mc_list) != NULL) { | 332 | while ((mc_lst = np->ipv6_mc_list) != NULL) { |
@@ -332,7 +335,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
332 | np->ipv6_mc_list = mc_lst->next; | 335 | np->ipv6_mc_list = mc_lst->next; |
333 | write_unlock_bh(&ipv6_sk_mc_lock); | 336 | write_unlock_bh(&ipv6_sk_mc_lock); |
334 | 337 | ||
335 | dev = dev_get_by_index(&init_net, mc_lst->ifindex); | 338 | dev = dev_get_by_index(net, mc_lst->ifindex); |
336 | if (dev) { | 339 | if (dev) { |
337 | struct inet6_dev *idev = in6_dev_get(dev); | 340 | struct inet6_dev *idev = in6_dev_get(dev); |
338 | 341 | ||
@@ -361,6 +364,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
361 | struct inet6_dev *idev; | 364 | struct inet6_dev *idev; |
362 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 365 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
363 | struct ip6_sf_socklist *psl; | 366 | struct ip6_sf_socklist *psl; |
367 | struct net *net = sock_net(sk); | ||
364 | int i, j, rv; | 368 | int i, j, rv; |
365 | int leavegroup = 0; | 369 | int leavegroup = 0; |
366 | int pmclocked = 0; | 370 | int pmclocked = 0; |
@@ -376,7 +380,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
376 | if (!ipv6_addr_is_multicast(group)) | 380 | if (!ipv6_addr_is_multicast(group)) |
377 | return -EINVAL; | 381 | return -EINVAL; |
378 | 382 | ||
379 | idev = ip6_mc_find_dev(group, pgsr->gsr_interface); | 383 | idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface); |
380 | if (!idev) | 384 | if (!idev) |
381 | return -ENODEV; | 385 | return -ENODEV; |
382 | dev = idev->dev; | 386 | dev = idev->dev; |
@@ -500,6 +504,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
500 | struct inet6_dev *idev; | 504 | struct inet6_dev *idev; |
501 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 505 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
502 | struct ip6_sf_socklist *newpsl, *psl; | 506 | struct ip6_sf_socklist *newpsl, *psl; |
507 | struct net *net = sock_net(sk); | ||
503 | int leavegroup = 0; | 508 | int leavegroup = 0; |
504 | int i, err; | 509 | int i, err; |
505 | 510 | ||
@@ -511,7 +516,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
511 | gsf->gf_fmode != MCAST_EXCLUDE) | 516 | gsf->gf_fmode != MCAST_EXCLUDE) |
512 | return -EINVAL; | 517 | return -EINVAL; |
513 | 518 | ||
514 | idev = ip6_mc_find_dev(group, gsf->gf_interface); | 519 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); |
515 | 520 | ||
516 | if (!idev) | 521 | if (!idev) |
517 | return -ENODEV; | 522 | return -ENODEV; |
@@ -592,13 +597,14 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
592 | struct net_device *dev; | 597 | struct net_device *dev; |
593 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 598 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
594 | struct ip6_sf_socklist *psl; | 599 | struct ip6_sf_socklist *psl; |
600 | struct net *net = sock_net(sk); | ||
595 | 601 | ||
596 | group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; | 602 | group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; |
597 | 603 | ||
598 | if (!ipv6_addr_is_multicast(group)) | 604 | if (!ipv6_addr_is_multicast(group)) |
599 | return -EINVAL; | 605 | return -EINVAL; |
600 | 606 | ||
601 | idev = ip6_mc_find_dev(group, gsf->gf_interface); | 607 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); |
602 | 608 | ||
603 | if (!idev) | 609 | if (!idev) |
604 | return -ENODEV; | 610 | return -ENODEV; |
@@ -656,8 +662,8 @@ done: | |||
656 | return err; | 662 | return err; |
657 | } | 663 | } |
658 | 664 | ||
659 | int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, | 665 | int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr, |
660 | struct in6_addr *src_addr) | 666 | const struct in6_addr *src_addr) |
661 | { | 667 | { |
662 | struct ipv6_pinfo *np = inet6_sk(sk); | 668 | struct ipv6_pinfo *np = inet6_sk(sk); |
663 | struct ipv6_mc_socklist *mc; | 669 | struct ipv6_mc_socklist *mc; |
@@ -863,7 +869,7 @@ static void mld_clear_delrec(struct inet6_dev *idev) | |||
863 | /* | 869 | /* |
864 | * device multicast group inc (add if not found) | 870 | * device multicast group inc (add if not found) |
865 | */ | 871 | */ |
866 | int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) | 872 | int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) |
867 | { | 873 | { |
868 | struct ifmcaddr6 *mc; | 874 | struct ifmcaddr6 *mc; |
869 | struct inet6_dev *idev; | 875 | struct inet6_dev *idev; |
@@ -934,7 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) | |||
934 | /* | 940 | /* |
935 | * device multicast group del | 941 | * device multicast group del |
936 | */ | 942 | */ |
937 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) | 943 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) |
938 | { | 944 | { |
939 | struct ifmcaddr6 *ma, **map; | 945 | struct ifmcaddr6 *ma, **map; |
940 | 946 | ||
@@ -959,7 +965,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) | |||
959 | return -ENOENT; | 965 | return -ENOENT; |
960 | } | 966 | } |
961 | 967 | ||
962 | int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr) | 968 | int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) |
963 | { | 969 | { |
964 | struct inet6_dev *idev = in6_dev_get(dev); | 970 | struct inet6_dev *idev = in6_dev_get(dev); |
965 | int err; | 971 | int err; |
@@ -1004,8 +1010,8 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr) | |||
1004 | /* | 1010 | /* |
1005 | * check if the interface/address pair is valid | 1011 | * check if the interface/address pair is valid |
1006 | */ | 1012 | */ |
1007 | int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, | 1013 | int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, |
1008 | struct in6_addr *src_addr) | 1014 | const struct in6_addr *src_addr) |
1009 | { | 1015 | { |
1010 | struct inet6_dev *idev; | 1016 | struct inet6_dev *idev; |
1011 | struct ifmcaddr6 *mc; | 1017 | struct ifmcaddr6 *mc; |
@@ -1393,10 +1399,12 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted) | |||
1393 | 1399 | ||
1394 | static struct sk_buff *mld_newpack(struct net_device *dev, int size) | 1400 | static struct sk_buff *mld_newpack(struct net_device *dev, int size) |
1395 | { | 1401 | { |
1396 | struct sock *sk = igmp6_socket->sk; | 1402 | struct net *net = dev_net(dev); |
1403 | struct sock *sk = net->ipv6.igmp_sk; | ||
1397 | struct sk_buff *skb; | 1404 | struct sk_buff *skb; |
1398 | struct mld2_report *pmr; | 1405 | struct mld2_report *pmr; |
1399 | struct in6_addr addr_buf; | 1406 | struct in6_addr addr_buf; |
1407 | const struct in6_addr *saddr; | ||
1400 | int err; | 1408 | int err; |
1401 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1409 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1402 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1410 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
@@ -1415,10 +1423,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1415 | * use unspecified address as the source address | 1423 | * use unspecified address as the source address |
1416 | * when a valid link-local address is not available. | 1424 | * when a valid link-local address is not available. |
1417 | */ | 1425 | */ |
1418 | memset(&addr_buf, 0, sizeof(addr_buf)); | 1426 | saddr = &in6addr_any; |
1419 | } | 1427 | } else |
1428 | saddr = &addr_buf; | ||
1420 | 1429 | ||
1421 | ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0); | 1430 | ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0); |
1422 | 1431 | ||
1423 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1432 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
1424 | 1433 | ||
@@ -1433,25 +1442,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1433 | return skb; | 1442 | return skb; |
1434 | } | 1443 | } |
1435 | 1444 | ||
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) | 1445 | static void mld_sendpack(struct sk_buff *skb) |
1456 | { | 1446 | { |
1457 | struct ipv6hdr *pip6 = ipv6_hdr(skb); | 1447 | struct ipv6hdr *pip6 = ipv6_hdr(skb); |
@@ -1459,7 +1449,9 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1459 | (struct mld2_report *)skb_transport_header(skb); | 1449 | (struct mld2_report *)skb_transport_header(skb); |
1460 | int payload_len, mldlen; | 1450 | int payload_len, mldlen; |
1461 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1451 | struct inet6_dev *idev = in6_dev_get(skb->dev); |
1452 | struct net *net = dev_net(skb->dev); | ||
1462 | int err; | 1453 | int err; |
1454 | struct flowi fl; | ||
1463 | 1455 | ||
1464 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); | 1456 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
1465 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); | 1457 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); |
@@ -1469,8 +1461,25 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1469 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1461 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
1470 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), | 1462 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), |
1471 | mldlen, 0)); | 1463 | mldlen, 0)); |
1464 | |||
1465 | skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | ||
1466 | |||
1467 | if (!skb->dst) { | ||
1468 | err = -ENOMEM; | ||
1469 | goto err_out; | ||
1470 | } | ||
1471 | |||
1472 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT, | ||
1473 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | ||
1474 | skb->dev->ifindex); | ||
1475 | |||
1476 | err = xfrm_lookup(&skb->dst, &fl, NULL, 0); | ||
1477 | if (err) | ||
1478 | goto err_out; | ||
1479 | |||
1472 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1480 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1473 | mld_dev_queue_xmit); | 1481 | dst_output); |
1482 | out: | ||
1474 | if (!err) { | 1483 | if (!err) { |
1475 | ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); | 1484 | ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); |
1476 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); | 1485 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); |
@@ -1480,6 +1489,11 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1480 | 1489 | ||
1481 | if (likely(idev != NULL)) | 1490 | if (likely(idev != NULL)) |
1482 | in6_dev_put(idev); | 1491 | in6_dev_put(idev); |
1492 | return; | ||
1493 | |||
1494 | err_out: | ||
1495 | kfree_skb(skb); | ||
1496 | goto out; | ||
1483 | } | 1497 | } |
1484 | 1498 | ||
1485 | static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) | 1499 | static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) |
@@ -1749,28 +1763,28 @@ static void mld_send_cr(struct inet6_dev *idev) | |||
1749 | 1763 | ||
1750 | static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | 1764 | static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) |
1751 | { | 1765 | { |
1752 | struct sock *sk = igmp6_socket->sk; | 1766 | struct net *net = dev_net(dev); |
1767 | struct sock *sk = net->ipv6.igmp_sk; | ||
1753 | struct inet6_dev *idev; | 1768 | struct inet6_dev *idev; |
1754 | struct sk_buff *skb; | 1769 | struct sk_buff *skb; |
1755 | struct icmp6hdr *hdr; | 1770 | struct icmp6hdr *hdr; |
1756 | struct in6_addr *snd_addr; | 1771 | const struct in6_addr *snd_addr, *saddr; |
1757 | struct in6_addr *addrp; | 1772 | struct in6_addr *addrp; |
1758 | struct in6_addr addr_buf; | 1773 | struct in6_addr addr_buf; |
1759 | struct in6_addr all_routers; | ||
1760 | int err, len, payload_len, full_len; | 1774 | int err, len, payload_len, full_len; |
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), |
1767 | IPSTATS_MIB_OUTREQUESTS); | 1782 | IPSTATS_MIB_OUTREQUESTS); |
1768 | rcu_read_unlock(); | 1783 | rcu_read_unlock(); |
1769 | snd_addr = addr; | 1784 | if (type == ICMPV6_MGM_REDUCTION) |
1770 | if (type == ICMPV6_MGM_REDUCTION) { | 1785 | snd_addr = &in6addr_linklocal_allrouters; |
1771 | snd_addr = &all_routers; | 1786 | else |
1772 | ipv6_addr_all_routers(&all_routers); | 1787 | snd_addr = addr; |
1773 | } | ||
1774 | 1788 | ||
1775 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); | 1789 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); |
1776 | payload_len = len + sizeof(ra); | 1790 | payload_len = len + sizeof(ra); |
@@ -1793,10 +1807,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1793 | * use unspecified address as the source address | 1807 | * use unspecified address as the source address |
1794 | * when a valid link-local address is not available. | 1808 | * when a valid link-local address is not available. |
1795 | */ | 1809 | */ |
1796 | memset(&addr_buf, 0, sizeof(addr_buf)); | 1810 | saddr = &in6addr_any; |
1797 | } | 1811 | } else |
1812 | saddr = &addr_buf; | ||
1798 | 1813 | ||
1799 | ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len); | 1814 | ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len); |
1800 | 1815 | ||
1801 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1816 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
1802 | 1817 | ||
@@ -1807,14 +1822,29 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1807 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); | 1822 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); |
1808 | ipv6_addr_copy(addrp, addr); | 1823 | ipv6_addr_copy(addrp, addr); |
1809 | 1824 | ||
1810 | hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len, | 1825 | hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, |
1811 | IPPROTO_ICMPV6, | 1826 | IPPROTO_ICMPV6, |
1812 | csum_partial((__u8 *) hdr, len, 0)); | 1827 | csum_partial((__u8 *) hdr, len, 0)); |
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, |
@@ -2276,24 +2310,19 @@ void ipv6_mc_init_dev(struct inet6_dev *idev) | |||
2276 | void ipv6_mc_destroy_dev(struct inet6_dev *idev) | 2310 | void ipv6_mc_destroy_dev(struct inet6_dev *idev) |
2277 | { | 2311 | { |
2278 | struct ifmcaddr6 *i; | 2312 | struct ifmcaddr6 *i; |
2279 | struct in6_addr maddr; | ||
2280 | 2313 | ||
2281 | /* Deactivate timers */ | 2314 | /* Deactivate timers */ |
2282 | ipv6_mc_down(idev); | 2315 | ipv6_mc_down(idev); |
2283 | 2316 | ||
2284 | /* Delete all-nodes address. */ | 2317 | /* Delete all-nodes address. */ |
2285 | ipv6_addr_all_nodes(&maddr); | ||
2286 | |||
2287 | /* We cannot call ipv6_dev_mc_dec() directly, our caller in | 2318 | /* We cannot call ipv6_dev_mc_dec() directly, our caller in |
2288 | * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will | 2319 | * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will |
2289 | * fail. | 2320 | * fail. |
2290 | */ | 2321 | */ |
2291 | __ipv6_dev_mc_dec(idev, &maddr); | 2322 | __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes); |
2292 | 2323 | ||
2293 | if (idev->cnf.forwarding) { | 2324 | if (idev->cnf.forwarding) |
2294 | ipv6_addr_all_routers(&maddr); | 2325 | __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters); |
2295 | __ipv6_dev_mc_dec(idev, &maddr); | ||
2296 | } | ||
2297 | 2326 | ||
2298 | write_lock_bh(&idev->lock); | 2327 | write_lock_bh(&idev->lock); |
2299 | while ((i = idev->mc_list) != NULL) { | 2328 | while ((i = idev->mc_list) != NULL) { |
@@ -2310,6 +2339,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev) | |||
2310 | 2339 | ||
2311 | #ifdef CONFIG_PROC_FS | 2340 | #ifdef CONFIG_PROC_FS |
2312 | struct igmp6_mc_iter_state { | 2341 | struct igmp6_mc_iter_state { |
2342 | struct seq_net_private p; | ||
2313 | struct net_device *dev; | 2343 | struct net_device *dev; |
2314 | struct inet6_dev *idev; | 2344 | struct inet6_dev *idev; |
2315 | }; | 2345 | }; |
@@ -2320,9 +2350,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq) | |||
2320 | { | 2350 | { |
2321 | struct ifmcaddr6 *im = NULL; | 2351 | struct ifmcaddr6 *im = NULL; |
2322 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); | 2352 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); |
2353 | struct net *net = seq_file_net(seq); | ||
2323 | 2354 | ||
2324 | state->idev = NULL; | 2355 | state->idev = NULL; |
2325 | for_each_netdev(&init_net, state->dev) { | 2356 | for_each_netdev(net, state->dev) { |
2326 | struct inet6_dev *idev; | 2357 | struct inet6_dev *idev; |
2327 | idev = in6_dev_get(state->dev); | 2358 | idev = in6_dev_get(state->dev); |
2328 | if (!idev) | 2359 | if (!idev) |
@@ -2424,8 +2455,8 @@ static const struct seq_operations igmp6_mc_seq_ops = { | |||
2424 | 2455 | ||
2425 | static int igmp6_mc_seq_open(struct inode *inode, struct file *file) | 2456 | static int igmp6_mc_seq_open(struct inode *inode, struct file *file) |
2426 | { | 2457 | { |
2427 | return seq_open_private(file, &igmp6_mc_seq_ops, | 2458 | return seq_open_net(inode, file, &igmp6_mc_seq_ops, |
2428 | sizeof(struct igmp6_mc_iter_state)); | 2459 | sizeof(struct igmp6_mc_iter_state)); |
2429 | } | 2460 | } |
2430 | 2461 | ||
2431 | static const struct file_operations igmp6_mc_seq_fops = { | 2462 | static const struct file_operations igmp6_mc_seq_fops = { |
@@ -2433,10 +2464,11 @@ static const struct file_operations igmp6_mc_seq_fops = { | |||
2433 | .open = igmp6_mc_seq_open, | 2464 | .open = igmp6_mc_seq_open, |
2434 | .read = seq_read, | 2465 | .read = seq_read, |
2435 | .llseek = seq_lseek, | 2466 | .llseek = seq_lseek, |
2436 | .release = seq_release_private, | 2467 | .release = seq_release_net, |
2437 | }; | 2468 | }; |
2438 | 2469 | ||
2439 | struct igmp6_mcf_iter_state { | 2470 | struct igmp6_mcf_iter_state { |
2471 | struct seq_net_private p; | ||
2440 | struct net_device *dev; | 2472 | struct net_device *dev; |
2441 | struct inet6_dev *idev; | 2473 | struct inet6_dev *idev; |
2442 | struct ifmcaddr6 *im; | 2474 | struct ifmcaddr6 *im; |
@@ -2449,10 +2481,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq) | |||
2449 | struct ip6_sf_list *psf = NULL; | 2481 | struct ip6_sf_list *psf = NULL; |
2450 | struct ifmcaddr6 *im = NULL; | 2482 | struct ifmcaddr6 *im = NULL; |
2451 | struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); | 2483 | struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); |
2484 | struct net *net = seq_file_net(seq); | ||
2452 | 2485 | ||
2453 | state->idev = NULL; | 2486 | state->idev = NULL; |
2454 | state->im = NULL; | 2487 | state->im = NULL; |
2455 | for_each_netdev(&init_net, state->dev) { | 2488 | for_each_netdev(net, state->dev) { |
2456 | struct inet6_dev *idev; | 2489 | struct inet6_dev *idev; |
2457 | idev = in6_dev_get(state->dev); | 2490 | idev = in6_dev_get(state->dev); |
2458 | if (unlikely(idev == NULL)) | 2491 | if (unlikely(idev == NULL)) |
@@ -2584,8 +2617,8 @@ static const struct seq_operations igmp6_mcf_seq_ops = { | |||
2584 | 2617 | ||
2585 | static int igmp6_mcf_seq_open(struct inode *inode, struct file *file) | 2618 | static int igmp6_mcf_seq_open(struct inode *inode, struct file *file) |
2586 | { | 2619 | { |
2587 | return seq_open_private(file, &igmp6_mcf_seq_ops, | 2620 | return seq_open_net(inode, file, &igmp6_mcf_seq_ops, |
2588 | sizeof(struct igmp6_mcf_iter_state)); | 2621 | sizeof(struct igmp6_mcf_iter_state)); |
2589 | } | 2622 | } |
2590 | 2623 | ||
2591 | static const struct file_operations igmp6_mcf_seq_fops = { | 2624 | static const struct file_operations igmp6_mcf_seq_fops = { |
@@ -2593,47 +2626,88 @@ static const struct file_operations igmp6_mcf_seq_fops = { | |||
2593 | .open = igmp6_mcf_seq_open, | 2626 | .open = igmp6_mcf_seq_open, |
2594 | .read = seq_read, | 2627 | .read = seq_read, |
2595 | .llseek = seq_lseek, | 2628 | .llseek = seq_lseek, |
2596 | .release = seq_release_private, | 2629 | .release = seq_release_net, |
2597 | }; | 2630 | }; |
2631 | |||
2632 | static int igmp6_proc_init(struct net *net) | ||
2633 | { | ||
2634 | int err; | ||
2635 | |||
2636 | err = -ENOMEM; | ||
2637 | if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops)) | ||
2638 | goto out; | ||
2639 | if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO, | ||
2640 | &igmp6_mcf_seq_fops)) | ||
2641 | goto out_proc_net_igmp6; | ||
2642 | |||
2643 | err = 0; | ||
2644 | out: | ||
2645 | return err; | ||
2646 | |||
2647 | out_proc_net_igmp6: | ||
2648 | proc_net_remove(net, "igmp6"); | ||
2649 | goto out; | ||
2650 | } | ||
2651 | |||
2652 | static void igmp6_proc_exit(struct net *net) | ||
2653 | { | ||
2654 | proc_net_remove(net, "mcfilter6"); | ||
2655 | proc_net_remove(net, "igmp6"); | ||
2656 | } | ||
2657 | #else | ||
2658 | static int igmp6_proc_init(struct net *net) | ||
2659 | { | ||
2660 | return 0; | ||
2661 | } | ||
2662 | static void igmp6_proc_exit(struct net *net) | ||
2663 | { | ||
2664 | ; | ||
2665 | } | ||
2598 | #endif | 2666 | #endif |
2599 | 2667 | ||
2600 | int __init igmp6_init(struct net_proto_family *ops) | 2668 | static int igmp6_net_init(struct net *net) |
2601 | { | 2669 | { |
2602 | struct ipv6_pinfo *np; | ||
2603 | struct sock *sk; | ||
2604 | int err; | 2670 | int err; |
2605 | 2671 | ||
2606 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket); | 2672 | err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6, |
2673 | SOCK_RAW, IPPROTO_ICMPV6, net); | ||
2607 | if (err < 0) { | 2674 | if (err < 0) { |
2608 | printk(KERN_ERR | 2675 | printk(KERN_ERR |
2609 | "Failed to initialize the IGMP6 control socket (err %d).\n", | 2676 | "Failed to initialize the IGMP6 control socket (err %d).\n", |
2610 | err); | 2677 | err); |
2611 | igmp6_socket = NULL; /* For safety. */ | 2678 | goto out; |
2612 | return err; | ||
2613 | } | 2679 | } |
2614 | 2680 | ||
2615 | sk = igmp6_socket->sk; | 2681 | inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1; |
2616 | sk->sk_allocation = GFP_ATOMIC; | ||
2617 | sk->sk_prot->unhash(sk); | ||
2618 | 2682 | ||
2619 | np = inet6_sk(sk); | 2683 | err = igmp6_proc_init(net); |
2620 | np->hop_limit = 1; | 2684 | if (err) |
2685 | goto out_sock_create; | ||
2686 | out: | ||
2687 | return err; | ||
2621 | 2688 | ||
2622 | #ifdef CONFIG_PROC_FS | 2689 | out_sock_create: |
2623 | proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops); | 2690 | inet_ctl_sock_destroy(net->ipv6.igmp_sk); |
2624 | proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops); | 2691 | goto out; |
2625 | #endif | 2692 | } |
2626 | 2693 | ||
2627 | return 0; | 2694 | static void igmp6_net_exit(struct net *net) |
2695 | { | ||
2696 | inet_ctl_sock_destroy(net->ipv6.igmp_sk); | ||
2697 | igmp6_proc_exit(net); | ||
2628 | } | 2698 | } |
2629 | 2699 | ||
2630 | void igmp6_cleanup(void) | 2700 | static struct pernet_operations igmp6_net_ops = { |
2701 | .init = igmp6_net_init, | ||
2702 | .exit = igmp6_net_exit, | ||
2703 | }; | ||
2704 | |||
2705 | int __init igmp6_init(void) | ||
2631 | { | 2706 | { |
2632 | sock_release(igmp6_socket); | 2707 | return register_pernet_subsys(&igmp6_net_ops); |
2633 | igmp6_socket = NULL; /* for safety */ | 2708 | } |
2634 | 2709 | ||
2635 | #ifdef CONFIG_PROC_FS | 2710 | void igmp6_cleanup(void) |
2636 | proc_net_remove(&init_net, "mcfilter6"); | 2711 | { |
2637 | proc_net_remove(&init_net, "igmp6"); | 2712 | unregister_pernet_subsys(&igmp6_net_ops); |
2638 | #endif | ||
2639 | } | 2713 | } |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index cd8a5bda13cd..ad1cc5bbf977 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -44,9 +44,9 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen) | |||
44 | if (!data) | 44 | if (!data) |
45 | return NULL; | 45 | return NULL; |
46 | if (padlen == 1) { | 46 | if (padlen == 1) { |
47 | data[0] = MIP6_OPT_PAD_1; | 47 | data[0] = IPV6_TLV_PAD0; |
48 | } else if (padlen > 1) { | 48 | } else if (padlen > 1) { |
49 | data[0] = MIP6_OPT_PAD_N; | 49 | data[0] = IPV6_TLV_PADN; |
50 | data[1] = padlen - 2; | 50 | data[1] = padlen - 2; |
51 | if (padlen > 2) | 51 | if (padlen > 2) |
52 | memset(data+2, 0, data[1]); | 52 | memset(data+2, 0, data[1]); |
@@ -304,13 +304,13 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
304 | static int mip6_destopt_init_state(struct xfrm_state *x) | 304 | static int mip6_destopt_init_state(struct xfrm_state *x) |
305 | { | 305 | { |
306 | if (x->id.spi) { | 306 | if (x->id.spi) { |
307 | printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__, | 307 | printk(KERN_INFO "%s: spi is not 0: %u\n", __func__, |
308 | x->id.spi); | 308 | x->id.spi); |
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | } | 310 | } |
311 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { | 311 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { |
312 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", | 312 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", |
313 | __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); | 313 | __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); |
314 | return -EINVAL; | 314 | return -EINVAL; |
315 | } | 315 | } |
316 | 316 | ||
@@ -439,13 +439,13 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
439 | static int mip6_rthdr_init_state(struct xfrm_state *x) | 439 | static int mip6_rthdr_init_state(struct xfrm_state *x) |
440 | { | 440 | { |
441 | if (x->id.spi) { | 441 | if (x->id.spi) { |
442 | printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__, | 442 | printk(KERN_INFO "%s: spi is not 0: %u\n", __func__, |
443 | x->id.spi); | 443 | x->id.spi); |
444 | return -EINVAL; | 444 | return -EINVAL; |
445 | } | 445 | } |
446 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { | 446 | if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { |
447 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", | 447 | printk(KERN_INFO "%s: state's mode is not %u: %u\n", |
448 | __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); | 448 | __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); |
449 | return -EINVAL; | 449 | return -EINVAL; |
450 | } | 450 | } |
451 | 451 | ||
@@ -480,15 +480,15 @@ static int __init mip6_init(void) | |||
480 | printk(KERN_INFO "Mobile IPv6\n"); | 480 | printk(KERN_INFO "Mobile IPv6\n"); |
481 | 481 | ||
482 | if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) { | 482 | if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) { |
483 | printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__); | 483 | printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __func__); |
484 | goto mip6_destopt_xfrm_fail; | 484 | goto mip6_destopt_xfrm_fail; |
485 | } | 485 | } |
486 | if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) { | 486 | if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) { |
487 | printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); | 487 | printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __func__); |
488 | goto mip6_rthdr_xfrm_fail; | 488 | goto mip6_rthdr_xfrm_fail; |
489 | } | 489 | } |
490 | if (rawv6_mh_filter_register(mip6_mh_filter) < 0) { | 490 | if (rawv6_mh_filter_register(mip6_mh_filter) < 0) { |
491 | printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__); | 491 | printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __func__); |
492 | goto mip6_rawv6_mh_fail; | 492 | goto mip6_rawv6_mh_fail; |
493 | } | 493 | } |
494 | 494 | ||
@@ -506,11 +506,11 @@ static int __init mip6_init(void) | |||
506 | static void __exit mip6_fini(void) | 506 | static void __exit mip6_fini(void) |
507 | { | 507 | { |
508 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) | 508 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) |
509 | printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__); | 509 | printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __func__); |
510 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) | 510 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) |
511 | printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); | 511 | printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __func__); |
512 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) | 512 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) |
513 | printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); | 513 | printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __func__); |
514 | } | 514 | } |
515 | 515 | ||
516 | module_init(mip6_init); | 516 | module_init(mip6_init); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 452a2ac4eec8..2c74885f8355 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -84,13 +84,12 @@ | |||
84 | 84 | ||
85 | #include <net/flow.h> | 85 | #include <net/flow.h> |
86 | #include <net/ip6_checksum.h> | 86 | #include <net/ip6_checksum.h> |
87 | #include <net/inet_common.h> | ||
87 | #include <linux/proc_fs.h> | 88 | #include <linux/proc_fs.h> |
88 | 89 | ||
89 | #include <linux/netfilter.h> | 90 | #include <linux/netfilter.h> |
90 | #include <linux/netfilter_ipv6.h> | 91 | #include <linux/netfilter_ipv6.h> |
91 | 92 | ||
92 | static struct socket *ndisc_socket; | ||
93 | |||
94 | static u32 ndisc_hash(const void *pkey, const struct net_device *dev); | 93 | static u32 ndisc_hash(const void *pkey, const struct net_device *dev); |
95 | static int ndisc_constructor(struct neighbour *neigh); | 94 | static int ndisc_constructor(struct neighbour *neigh); |
96 | static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); | 95 | static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); |
@@ -270,7 +269,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, | |||
270 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { | 269 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { |
271 | ND_PRINTK2(KERN_WARNING | 270 | ND_PRINTK2(KERN_WARNING |
272 | "%s(): duplicated ND6 option found: type=%d\n", | 271 | "%s(): duplicated ND6 option found: type=%d\n", |
273 | __FUNCTION__, | 272 | __func__, |
274 | nd_opt->nd_opt_type); | 273 | nd_opt->nd_opt_type); |
275 | } else { | 274 | } else { |
276 | ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; | 275 | ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; |
@@ -301,7 +300,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, | |||
301 | */ | 300 | */ |
302 | ND_PRINTK2(KERN_NOTICE | 301 | ND_PRINTK2(KERN_NOTICE |
303 | "%s(): ignored unsupported option; type=%d, len=%d\n", | 302 | "%s(): ignored unsupported option; type=%d, len=%d\n", |
304 | __FUNCTION__, | 303 | __func__, |
305 | nd_opt->nd_opt_type, nd_opt->nd_opt_len); | 304 | nd_opt->nd_opt_type, nd_opt->nd_opt_len); |
306 | } | 305 | } |
307 | } | 306 | } |
@@ -441,30 +440,17 @@ static void pndisc_destructor(struct pneigh_entry *n) | |||
441 | /* | 440 | /* |
442 | * Send a Neighbour Advertisement | 441 | * Send a Neighbour Advertisement |
443 | */ | 442 | */ |
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, | 443 | static void __ndisc_send(struct net_device *dev, |
460 | struct neighbour *neigh, | 444 | struct neighbour *neigh, |
461 | struct in6_addr *daddr, struct in6_addr *saddr, | 445 | const struct in6_addr *daddr, |
462 | struct icmp6hdr *icmp6h, struct in6_addr *target, | 446 | const struct in6_addr *saddr, |
447 | struct icmp6hdr *icmp6h, const struct in6_addr *target, | ||
463 | int llinfo) | 448 | int llinfo) |
464 | { | 449 | { |
465 | struct flowi fl; | 450 | struct flowi fl; |
466 | struct dst_entry *dst; | 451 | struct dst_entry *dst; |
467 | struct sock *sk = ndisc_socket->sk; | 452 | struct net *net = dev_net(dev); |
453 | struct sock *sk = net->ipv6.ndisc_sk; | ||
468 | struct sk_buff *skb; | 454 | struct sk_buff *skb; |
469 | struct icmp6hdr *hdr; | 455 | struct icmp6hdr *hdr; |
470 | struct inet6_dev *idev; | 456 | struct inet6_dev *idev; |
@@ -474,10 +460,9 @@ static void __ndisc_send(struct net_device *dev, | |||
474 | 460 | ||
475 | type = icmp6h->icmp6_type; | 461 | type = icmp6h->icmp6_type; |
476 | 462 | ||
477 | ndisc_flow_init(&fl, type, saddr, daddr, | 463 | icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex); |
478 | dev->ifindex); | ||
479 | 464 | ||
480 | dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); | 465 | dst = icmp6_dst_alloc(dev, neigh, daddr); |
481 | if (!dst) | 466 | if (!dst) |
482 | return; | 467 | return; |
483 | 468 | ||
@@ -499,7 +484,7 @@ static void __ndisc_send(struct net_device *dev, | |||
499 | if (!skb) { | 484 | if (!skb) { |
500 | ND_PRINTK0(KERN_ERR | 485 | ND_PRINTK0(KERN_ERR |
501 | "ICMPv6 ND: %s() failed to allocate an skb.\n", | 486 | "ICMPv6 ND: %s() failed to allocate an skb.\n", |
502 | __FUNCTION__); | 487 | __func__); |
503 | dst_release(dst); | 488 | dst_release(dst); |
504 | return; | 489 | return; |
505 | } | 490 | } |
@@ -545,25 +530,28 @@ static void __ndisc_send(struct net_device *dev, | |||
545 | } | 530 | } |
546 | 531 | ||
547 | static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | 532 | static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, |
548 | struct in6_addr *daddr, struct in6_addr *solicited_addr, | 533 | const struct in6_addr *daddr, |
549 | int router, int solicited, int override, int inc_opt) | 534 | const struct in6_addr *solicited_addr, |
535 | int router, int solicited, int override, int inc_opt) | ||
550 | { | 536 | { |
551 | struct in6_addr tmpaddr; | 537 | struct in6_addr tmpaddr; |
552 | struct inet6_ifaddr *ifp; | 538 | struct inet6_ifaddr *ifp; |
553 | struct in6_addr *src_addr; | 539 | const struct in6_addr *src_addr; |
554 | struct icmp6hdr icmp6h = { | 540 | struct icmp6hdr icmp6h = { |
555 | .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, | 541 | .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, |
556 | }; | 542 | }; |
557 | 543 | ||
558 | /* for anycast or proxy, solicited_addr != src_addr */ | 544 | /* for anycast or proxy, solicited_addr != src_addr */ |
559 | ifp = ipv6_get_ifaddr(&init_net, solicited_addr, dev, 1); | 545 | ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1); |
560 | if (ifp) { | 546 | if (ifp) { |
561 | src_addr = solicited_addr; | 547 | src_addr = solicited_addr; |
562 | if (ifp->flags & IFA_F_OPTIMISTIC) | 548 | if (ifp->flags & IFA_F_OPTIMISTIC) |
563 | override = 0; | 549 | override = 0; |
564 | in6_ifa_put(ifp); | 550 | in6_ifa_put(ifp); |
565 | } else { | 551 | } else { |
566 | if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) | 552 | if (ipv6_dev_get_saddr(dev, daddr, |
553 | inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs, | ||
554 | &tmpaddr)) | ||
567 | return; | 555 | return; |
568 | src_addr = &tmpaddr; | 556 | src_addr = &tmpaddr; |
569 | } | 557 | } |
@@ -578,8 +566,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
578 | } | 566 | } |
579 | 567 | ||
580 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | 568 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, |
581 | struct in6_addr *solicit, | 569 | const struct in6_addr *solicit, |
582 | struct in6_addr *daddr, struct in6_addr *saddr) | 570 | const struct in6_addr *daddr, const struct in6_addr *saddr) |
583 | { | 571 | { |
584 | struct in6_addr addr_buf; | 572 | struct in6_addr addr_buf; |
585 | struct icmp6hdr icmp6h = { | 573 | struct icmp6hdr icmp6h = { |
@@ -598,8 +586,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
598 | !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0); | 586 | !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0); |
599 | } | 587 | } |
600 | 588 | ||
601 | void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | 589 | void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, |
602 | struct in6_addr *daddr) | 590 | const struct in6_addr *daddr) |
603 | { | 591 | { |
604 | struct icmp6hdr icmp6h = { | 592 | struct icmp6hdr icmp6h = { |
605 | .icmp6_type = NDISC_ROUTER_SOLICITATION, | 593 | .icmp6_type = NDISC_ROUTER_SOLICITATION, |
@@ -616,7 +604,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
616 | * suppress the inclusion of the sllao. | 604 | * suppress the inclusion of the sllao. |
617 | */ | 605 | */ |
618 | if (send_sllao) { | 606 | if (send_sllao) { |
619 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr, | 607 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr, |
620 | dev, 1); | 608 | dev, 1); |
621 | if (ifp) { | 609 | if (ifp) { |
622 | if (ifp->flags & IFA_F_OPTIMISTIC) { | 610 | if (ifp->flags & IFA_F_OPTIMISTIC) { |
@@ -654,7 +642,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
654 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; | 642 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; |
655 | int probes = atomic_read(&neigh->probes); | 643 | int probes = atomic_read(&neigh->probes); |
656 | 644 | ||
657 | if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1)) | 645 | if (skb && ipv6_chk_addr(dev_net(dev), &ipv6_hdr(skb)->saddr, dev, 1)) |
658 | saddr = &ipv6_hdr(skb)->saddr; | 646 | saddr = &ipv6_hdr(skb)->saddr; |
659 | 647 | ||
660 | if ((probes -= neigh->parms->ucast_probes) < 0) { | 648 | if ((probes -= neigh->parms->ucast_probes) < 0) { |
@@ -662,7 +650,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
662 | ND_PRINTK1(KERN_DEBUG | 650 | ND_PRINTK1(KERN_DEBUG |
663 | "%s(): trying to ucast probe in NUD_INVALID: " | 651 | "%s(): trying to ucast probe in NUD_INVALID: " |
664 | NIP6_FMT "\n", | 652 | NIP6_FMT "\n", |
665 | __FUNCTION__, | 653 | __func__, |
666 | NIP6(*target)); | 654 | NIP6(*target)); |
667 | } | 655 | } |
668 | ndisc_send_ns(dev, neigh, target, target, saddr); | 656 | ndisc_send_ns(dev, neigh, target, target, saddr); |
@@ -676,18 +664,19 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
676 | } | 664 | } |
677 | } | 665 | } |
678 | 666 | ||
679 | static struct pneigh_entry *pndisc_check_router(struct net_device *dev, | 667 | static int pndisc_is_router(const void *pkey, |
680 | struct in6_addr *addr, int *is_router) | 668 | struct net_device *dev) |
681 | { | 669 | { |
682 | struct pneigh_entry *n; | 670 | struct pneigh_entry *n; |
671 | int ret = -1; | ||
683 | 672 | ||
684 | read_lock_bh(&nd_tbl.lock); | 673 | read_lock_bh(&nd_tbl.lock); |
685 | n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev); | 674 | n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev); |
686 | if (n != NULL) | 675 | if (n) |
687 | *is_router = (n->flags & NTF_ROUTER); | 676 | ret = !!(n->flags & NTF_ROUTER); |
688 | read_unlock_bh(&nd_tbl.lock); | 677 | read_unlock_bh(&nd_tbl.lock); |
689 | 678 | ||
690 | return n; | 679 | return ret; |
691 | } | 680 | } |
692 | 681 | ||
693 | static void ndisc_recv_ns(struct sk_buff *skb) | 682 | static void ndisc_recv_ns(struct sk_buff *skb) |
@@ -703,10 +692,9 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
703 | struct inet6_ifaddr *ifp; | 692 | struct inet6_ifaddr *ifp; |
704 | struct inet6_dev *idev = NULL; | 693 | struct inet6_dev *idev = NULL; |
705 | struct neighbour *neigh; | 694 | struct neighbour *neigh; |
706 | struct pneigh_entry *pneigh = NULL; | ||
707 | int dad = ipv6_addr_any(saddr); | 695 | int dad = ipv6_addr_any(saddr); |
708 | int inc; | 696 | int inc; |
709 | int is_router = 0; | 697 | int is_router = -1; |
710 | 698 | ||
711 | if (ipv6_addr_is_multicast(&msg->target)) { | 699 | if (ipv6_addr_is_multicast(&msg->target)) { |
712 | ND_PRINTK2(KERN_WARNING | 700 | ND_PRINTK2(KERN_WARNING |
@@ -756,7 +744,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
756 | 744 | ||
757 | inc = ipv6_addr_is_multicast(daddr); | 745 | inc = ipv6_addr_is_multicast(daddr); |
758 | 746 | ||
759 | if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) { | 747 | ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); |
748 | if (ifp) { | ||
760 | 749 | ||
761 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { | 750 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { |
762 | if (dad) { | 751 | if (dad) { |
@@ -801,11 +790,10 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
801 | return; | 790 | return; |
802 | } | 791 | } |
803 | 792 | ||
804 | if (ipv6_chk_acast_addr(dev, &msg->target) || | 793 | if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) || |
805 | (idev->cnf.forwarding && | 794 | (idev->cnf.forwarding && |
806 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && | 795 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && |
807 | (pneigh = pndisc_check_router(dev, &msg->target, | 796 | (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) { |
808 | &is_router)) != NULL)) { | ||
809 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && | 797 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && |
810 | skb->pkt_type != PACKET_HOST && | 798 | skb->pkt_type != PACKET_HOST && |
811 | inc != 0 && | 799 | inc != 0 && |
@@ -826,13 +814,11 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
826 | goto out; | 814 | goto out; |
827 | } | 815 | } |
828 | 816 | ||
829 | is_router = !!(pneigh ? is_router : idev->cnf.forwarding); | 817 | if (is_router < 0) |
818 | is_router = !!idev->cnf.forwarding; | ||
830 | 819 | ||
831 | if (dad) { | 820 | if (dad) { |
832 | struct in6_addr maddr; | 821 | ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target, |
833 | |||
834 | ipv6_addr_all_nodes(&maddr); | ||
835 | ndisc_send_na(dev, NULL, &maddr, &msg->target, | ||
836 | is_router, 0, (ifp != NULL), 1); | 822 | is_router, 0, (ifp != NULL), 1); |
837 | goto out; | 823 | goto out; |
838 | } | 824 | } |
@@ -914,7 +900,8 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
914 | return; | 900 | return; |
915 | } | 901 | } |
916 | } | 902 | } |
917 | if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) { | 903 | ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); |
904 | if (ifp) { | ||
918 | if (ifp->flags & IFA_F_TENTATIVE) { | 905 | if (ifp->flags & IFA_F_TENTATIVE) { |
919 | addrconf_dad_failure(ifp); | 906 | addrconf_dad_failure(ifp); |
920 | return; | 907 | return; |
@@ -945,7 +932,7 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
945 | */ | 932 | */ |
946 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && | 933 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && |
947 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && | 934 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && |
948 | pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) { | 935 | pneigh_lookup(&nd_tbl, dev_net(dev), &msg->target, dev, 0)) { |
949 | /* XXX: idev->cnf.prixy_ndp */ | 936 | /* XXX: idev->cnf.prixy_ndp */ |
950 | goto out; | 937 | goto out; |
951 | } | 938 | } |
@@ -1035,6 +1022,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1035 | struct sk_buff *skb; | 1022 | struct sk_buff *skb; |
1036 | struct nlmsghdr *nlh; | 1023 | struct nlmsghdr *nlh; |
1037 | struct nduseroptmsg *ndmsg; | 1024 | struct nduseroptmsg *ndmsg; |
1025 | struct net *net = dev_net(ra->dev); | ||
1038 | int err; | 1026 | int err; |
1039 | int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) | 1027 | int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) |
1040 | + (opt->nd_opt_len << 3)); | 1028 | + (opt->nd_opt_len << 3)); |
@@ -1064,7 +1052,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1064 | &ipv6_hdr(ra)->saddr); | 1052 | &ipv6_hdr(ra)->saddr); |
1065 | nlmsg_end(skb, nlh); | 1053 | nlmsg_end(skb, nlh); |
1066 | 1054 | ||
1067 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL, | 1055 | err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, |
1068 | GFP_ATOMIC); | 1056 | GFP_ATOMIC); |
1069 | if (err < 0) | 1057 | if (err < 0) |
1070 | goto errout; | 1058 | goto errout; |
@@ -1075,7 +1063,7 @@ nla_put_failure: | |||
1075 | nlmsg_free(skb); | 1063 | nlmsg_free(skb); |
1076 | err = -EMSGSIZE; | 1064 | err = -EMSGSIZE; |
1077 | errout: | 1065 | errout: |
1078 | rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err); | 1066 | rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err); |
1079 | } | 1067 | } |
1080 | 1068 | ||
1081 | static void ndisc_router_discovery(struct sk_buff *skb) | 1069 | static void ndisc_router_discovery(struct sk_buff *skb) |
@@ -1104,6 +1092,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1104 | return; | 1092 | return; |
1105 | } | 1093 | } |
1106 | 1094 | ||
1095 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | ||
1096 | if (skb->ndisc_nodetype == NDISC_NODETYPE_HOST) { | ||
1097 | ND_PRINTK2(KERN_WARNING | ||
1098 | "ICMPv6 RA: from host or unauthorized router\n"); | ||
1099 | return; | ||
1100 | } | ||
1101 | #endif | ||
1102 | |||
1107 | /* | 1103 | /* |
1108 | * set the RA_RECV flag in the interface | 1104 | * set the RA_RECV flag in the interface |
1109 | */ | 1105 | */ |
@@ -1127,6 +1123,12 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1127 | return; | 1123 | return; |
1128 | } | 1124 | } |
1129 | 1125 | ||
1126 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | ||
1127 | /* skip link-specific parameters from interior routers */ | ||
1128 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) | ||
1129 | goto skip_linkparms; | ||
1130 | #endif | ||
1131 | |||
1130 | if (in6_dev->if_flags & IF_RS_SENT) { | 1132 | if (in6_dev->if_flags & IF_RS_SENT) { |
1131 | /* | 1133 | /* |
1132 | * flag that an RA was received after an RS was sent | 1134 | * flag that an RA was received after an RS was sent |
@@ -1178,7 +1180,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1178 | if (rt == NULL) { | 1180 | if (rt == NULL) { |
1179 | ND_PRINTK0(KERN_ERR | 1181 | ND_PRINTK0(KERN_ERR |
1180 | "ICMPv6 RA: %s() failed to add default route.\n", | 1182 | "ICMPv6 RA: %s() failed to add default route.\n", |
1181 | __FUNCTION__); | 1183 | __func__); |
1182 | in6_dev_put(in6_dev); | 1184 | in6_dev_put(in6_dev); |
1183 | return; | 1185 | return; |
1184 | } | 1186 | } |
@@ -1187,7 +1189,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1187 | if (neigh == NULL) { | 1189 | if (neigh == NULL) { |
1188 | ND_PRINTK0(KERN_ERR | 1190 | ND_PRINTK0(KERN_ERR |
1189 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1191 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
1190 | __FUNCTION__); | 1192 | __func__); |
1191 | dst_release(&rt->u.dst); | 1193 | dst_release(&rt->u.dst); |
1192 | in6_dev_put(in6_dev); | 1194 | in6_dev_put(in6_dev); |
1193 | return; | 1195 | return; |
@@ -1241,6 +1243,10 @@ skip_defrtr: | |||
1241 | } | 1243 | } |
1242 | } | 1244 | } |
1243 | 1245 | ||
1246 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | ||
1247 | skip_linkparms: | ||
1248 | #endif | ||
1249 | |||
1244 | /* | 1250 | /* |
1245 | * Process options. | 1251 | * Process options. |
1246 | */ | 1252 | */ |
@@ -1272,7 +1278,13 @@ skip_defrtr: | |||
1272 | for (p = ndopts.nd_opts_ri; | 1278 | for (p = ndopts.nd_opts_ri; |
1273 | p; | 1279 | p; |
1274 | p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) { | 1280 | p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) { |
1275 | if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) | 1281 | struct route_info *ri = (struct route_info *)p; |
1282 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | ||
1283 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT && | ||
1284 | ri->prefix_len == 0) | ||
1285 | continue; | ||
1286 | #endif | ||
1287 | if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) | ||
1276 | continue; | 1288 | continue; |
1277 | rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, | 1289 | rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, |
1278 | &ipv6_hdr(skb)->saddr); | 1290 | &ipv6_hdr(skb)->saddr); |
@@ -1280,6 +1292,12 @@ skip_defrtr: | |||
1280 | } | 1292 | } |
1281 | #endif | 1293 | #endif |
1282 | 1294 | ||
1295 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | ||
1296 | /* skip link-specific ndopts from interior routers */ | ||
1297 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) | ||
1298 | goto out; | ||
1299 | #endif | ||
1300 | |||
1283 | if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { | 1301 | if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { |
1284 | struct nd_opt_hdr *p; | 1302 | struct nd_opt_hdr *p; |
1285 | for (p = ndopts.nd_opts_pi; | 1303 | for (p = ndopts.nd_opts_pi; |
@@ -1343,6 +1361,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1343 | int optlen; | 1361 | int optlen; |
1344 | u8 *lladdr = NULL; | 1362 | u8 *lladdr = NULL; |
1345 | 1363 | ||
1364 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | ||
1365 | switch (skb->ndisc_nodetype) { | ||
1366 | case NDISC_NODETYPE_HOST: | ||
1367 | case NDISC_NODETYPE_NODEFAULT: | ||
1368 | ND_PRINTK2(KERN_WARNING | ||
1369 | "ICMPv6 Redirect: from host or unauthorized router\n"); | ||
1370 | return; | ||
1371 | } | ||
1372 | #endif | ||
1373 | |||
1346 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { | 1374 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { |
1347 | ND_PRINTK2(KERN_WARNING | 1375 | ND_PRINTK2(KERN_WARNING |
1348 | "ICMPv6 Redirect: source address is not link-local.\n"); | 1376 | "ICMPv6 Redirect: source address is not link-local.\n"); |
@@ -1418,15 +1446,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1418 | } | 1446 | } |
1419 | 1447 | ||
1420 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | 1448 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, |
1421 | struct in6_addr *target) | 1449 | const struct in6_addr *target) |
1422 | { | 1450 | { |
1423 | struct sock *sk = ndisc_socket->sk; | 1451 | struct net_device *dev = skb->dev; |
1452 | struct net *net = dev_net(dev); | ||
1453 | struct sock *sk = net->ipv6.ndisc_sk; | ||
1424 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); | 1454 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); |
1425 | struct sk_buff *buff; | 1455 | struct sk_buff *buff; |
1426 | struct icmp6hdr *icmph; | 1456 | struct icmp6hdr *icmph; |
1427 | struct in6_addr saddr_buf; | 1457 | struct in6_addr saddr_buf; |
1428 | struct in6_addr *addrp; | 1458 | struct in6_addr *addrp; |
1429 | struct net_device *dev; | ||
1430 | struct rt6_info *rt; | 1459 | struct rt6_info *rt; |
1431 | struct dst_entry *dst; | 1460 | struct dst_entry *dst; |
1432 | struct inet6_dev *idev; | 1461 | struct inet6_dev *idev; |
@@ -1436,8 +1465,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1436 | int err; | 1465 | int err; |
1437 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; | 1466 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; |
1438 | 1467 | ||
1439 | dev = skb->dev; | ||
1440 | |||
1441 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { | 1468 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { |
1442 | ND_PRINTK2(KERN_WARNING | 1469 | ND_PRINTK2(KERN_WARNING |
1443 | "ICMPv6 Redirect: no link-local address on %s\n", | 1470 | "ICMPv6 Redirect: no link-local address on %s\n", |
@@ -1452,10 +1479,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1452 | return; | 1479 | return; |
1453 | } | 1480 | } |
1454 | 1481 | ||
1455 | ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1482 | icmpv6_flow_init(sk, &fl, NDISC_REDIRECT, |
1456 | dev->ifindex); | 1483 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); |
1457 | 1484 | ||
1458 | dst = ip6_route_output(NULL, &fl); | 1485 | dst = ip6_route_output(net, NULL, &fl); |
1459 | if (dst == NULL) | 1486 | if (dst == NULL) |
1460 | return; | 1487 | return; |
1461 | 1488 | ||
@@ -1499,12 +1526,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1499 | if (buff == NULL) { | 1526 | if (buff == NULL) { |
1500 | ND_PRINTK0(KERN_ERR | 1527 | ND_PRINTK0(KERN_ERR |
1501 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", | 1528 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", |
1502 | __FUNCTION__); | 1529 | __func__); |
1503 | dst_release(dst); | 1530 | dst_release(dst); |
1504 | return; | 1531 | return; |
1505 | } | 1532 | } |
1506 | 1533 | ||
1507 | |||
1508 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1534 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); |
1509 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1535 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, |
1510 | IPPROTO_ICMPV6, len); | 1536 | IPPROTO_ICMPV6, len); |
@@ -1625,18 +1651,16 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1625 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1651 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1626 | { | 1652 | { |
1627 | struct net_device *dev = ptr; | 1653 | struct net_device *dev = ptr; |
1628 | 1654 | struct net *net = dev_net(dev); | |
1629 | if (dev->nd_net != &init_net) | ||
1630 | return NOTIFY_DONE; | ||
1631 | 1655 | ||
1632 | switch (event) { | 1656 | switch (event) { |
1633 | case NETDEV_CHANGEADDR: | 1657 | case NETDEV_CHANGEADDR: |
1634 | neigh_changeaddr(&nd_tbl, dev); | 1658 | neigh_changeaddr(&nd_tbl, dev); |
1635 | fib6_run_gc(~0UL); | 1659 | fib6_run_gc(~0UL, net); |
1636 | break; | 1660 | break; |
1637 | case NETDEV_DOWN: | 1661 | case NETDEV_DOWN: |
1638 | neigh_ifdown(&nd_tbl, dev); | 1662 | neigh_ifdown(&nd_tbl, dev); |
1639 | fib6_run_gc(~0UL); | 1663 | fib6_run_gc(~0UL, net); |
1640 | break; | 1664 | break; |
1641 | default: | 1665 | default: |
1642 | break; | 1666 | break; |
@@ -1745,44 +1769,74 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, | |||
1745 | 1769 | ||
1746 | #endif | 1770 | #endif |
1747 | 1771 | ||
1748 | int __init ndisc_init(struct net_proto_family *ops) | 1772 | static int ndisc_net_init(struct net *net) |
1749 | { | 1773 | { |
1750 | struct ipv6_pinfo *np; | 1774 | struct ipv6_pinfo *np; |
1751 | struct sock *sk; | 1775 | struct sock *sk; |
1752 | int err; | 1776 | int err; |
1753 | 1777 | ||
1754 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket); | 1778 | err = inet_ctl_sock_create(&sk, PF_INET6, |
1779 | SOCK_RAW, IPPROTO_ICMPV6, net); | ||
1755 | if (err < 0) { | 1780 | if (err < 0) { |
1756 | ND_PRINTK0(KERN_ERR | 1781 | ND_PRINTK0(KERN_ERR |
1757 | "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", | 1782 | "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", |
1758 | err); | 1783 | err); |
1759 | ndisc_socket = NULL; /* For safety. */ | ||
1760 | return err; | 1784 | return err; |
1761 | } | 1785 | } |
1762 | 1786 | ||
1763 | sk = ndisc_socket->sk; | 1787 | net->ipv6.ndisc_sk = sk; |
1788 | |||
1764 | np = inet6_sk(sk); | 1789 | np = inet6_sk(sk); |
1765 | sk->sk_allocation = GFP_ATOMIC; | ||
1766 | np->hop_limit = 255; | 1790 | np->hop_limit = 255; |
1767 | /* Do not loopback ndisc messages */ | 1791 | /* Do not loopback ndisc messages */ |
1768 | np->mc_loop = 0; | 1792 | np->mc_loop = 0; |
1769 | sk->sk_prot->unhash(sk); | ||
1770 | 1793 | ||
1794 | return 0; | ||
1795 | } | ||
1796 | |||
1797 | static void ndisc_net_exit(struct net *net) | ||
1798 | { | ||
1799 | inet_ctl_sock_destroy(net->ipv6.ndisc_sk); | ||
1800 | } | ||
1801 | |||
1802 | static struct pernet_operations ndisc_net_ops = { | ||
1803 | .init = ndisc_net_init, | ||
1804 | .exit = ndisc_net_exit, | ||
1805 | }; | ||
1806 | |||
1807 | int __init ndisc_init(void) | ||
1808 | { | ||
1809 | int err; | ||
1810 | |||
1811 | err = register_pernet_subsys(&ndisc_net_ops); | ||
1812 | if (err) | ||
1813 | return err; | ||
1771 | /* | 1814 | /* |
1772 | * Initialize the neighbour table | 1815 | * Initialize the neighbour table |
1773 | */ | 1816 | */ |
1774 | |||
1775 | neigh_table_init(&nd_tbl); | 1817 | neigh_table_init(&nd_tbl); |
1776 | 1818 | ||
1777 | #ifdef CONFIG_SYSCTL | 1819 | #ifdef CONFIG_SYSCTL |
1778 | neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, | 1820 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, |
1779 | "ipv6", | 1821 | NET_IPV6_NEIGH, "ipv6", |
1780 | &ndisc_ifinfo_sysctl_change, | 1822 | &ndisc_ifinfo_sysctl_change, |
1781 | &ndisc_ifinfo_sysctl_strategy); | 1823 | &ndisc_ifinfo_sysctl_strategy); |
1824 | if (err) | ||
1825 | goto out_unregister_pernet; | ||
1782 | #endif | 1826 | #endif |
1827 | err = register_netdevice_notifier(&ndisc_netdev_notifier); | ||
1828 | if (err) | ||
1829 | goto out_unregister_sysctl; | ||
1830 | out: | ||
1831 | return err; | ||
1783 | 1832 | ||
1784 | register_netdevice_notifier(&ndisc_netdev_notifier); | 1833 | out_unregister_sysctl: |
1785 | return 0; | 1834 | #ifdef CONFIG_SYSCTL |
1835 | neigh_sysctl_unregister(&nd_tbl.parms); | ||
1836 | out_unregister_pernet: | ||
1837 | #endif | ||
1838 | unregister_pernet_subsys(&ndisc_net_ops); | ||
1839 | goto out; | ||
1786 | } | 1840 | } |
1787 | 1841 | ||
1788 | void ndisc_cleanup(void) | 1842 | void ndisc_cleanup(void) |
@@ -1792,6 +1846,5 @@ void ndisc_cleanup(void) | |||
1792 | neigh_sysctl_unregister(&nd_tbl.parms); | 1846 | neigh_sysctl_unregister(&nd_tbl.parms); |
1793 | #endif | 1847 | #endif |
1794 | neigh_table_clear(&nd_tbl); | 1848 | neigh_table_clear(&nd_tbl); |
1795 | sock_release(ndisc_socket); | 1849 | unregister_pernet_subsys(&ndisc_net_ops); |
1796 | ndisc_socket = NULL; /* For safety. */ | ||
1797 | } | 1850 | } |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 2e06724dc348..aed51bcc66b4 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -23,7 +23,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
23 | .saddr = iph->saddr, } }, | 23 | .saddr = iph->saddr, } }, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | dst = ip6_route_output(skb->sk, &fl); | 26 | dst = ip6_route_output(&init_net, skb->sk, &fl); |
27 | 27 | ||
28 | #ifdef CONFIG_XFRM | 28 | #ifdef CONFIG_XFRM |
29 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | 29 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && |
@@ -86,7 +86,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
86 | 86 | ||
87 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) | 87 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) |
88 | { | 88 | { |
89 | *dst = ip6_route_output(NULL, fl); | 89 | *dst = ip6_route_output(&init_net, NULL, fl); |
90 | return (*dst)->error; | 90 | return (*dst)->error; |
91 | } | 91 | } |
92 | 92 | ||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 8d366f7f2a9a..92a36c9e5402 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -484,7 +484,7 @@ ipq_rcv_dev_event(struct notifier_block *this, | |||
484 | { | 484 | { |
485 | struct net_device *dev = ptr; | 485 | struct net_device *dev = ptr; |
486 | 486 | ||
487 | if (dev->nd_net != &init_net) | 487 | if (dev_net(dev) != &init_net) |
488 | return NOTIFY_DONE; | 488 | return NOTIFY_DONE; |
489 | 489 | ||
490 | /* Drop any packets associated with the downed device */ | 490 | /* Drop any packets associated with the downed device */ |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index bf9bb6e55bb5..70ef0d276cc0 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -55,7 +55,7 @@ MODULE_DESCRIPTION("IPv6 packet filter"); | |||
55 | do { \ | 55 | do { \ |
56 | if (!(x)) \ | 56 | if (!(x)) \ |
57 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ | 57 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ |
58 | __FUNCTION__, __FILE__, __LINE__); \ | 58 | __func__, __FILE__, __LINE__); \ |
59 | } while(0) | 59 | } while(0) |
60 | #else | 60 | #else |
61 | #define IP_NF_ASSERT(x) | 61 | #define IP_NF_ASSERT(x) |
@@ -1879,11 +1879,11 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, | |||
1879 | 1879 | ||
1880 | switch (cmd) { | 1880 | switch (cmd) { |
1881 | case IP6T_SO_SET_REPLACE: | 1881 | case IP6T_SO_SET_REPLACE: |
1882 | ret = compat_do_replace(sk->sk_net, user, len); | 1882 | ret = compat_do_replace(sock_net(sk), user, len); |
1883 | break; | 1883 | break; |
1884 | 1884 | ||
1885 | case IP6T_SO_SET_ADD_COUNTERS: | 1885 | case IP6T_SO_SET_ADD_COUNTERS: |
1886 | ret = do_add_counters(sk->sk_net, user, len, 1); | 1886 | ret = do_add_counters(sock_net(sk), user, len, 1); |
1887 | break; | 1887 | break; |
1888 | 1888 | ||
1889 | default: | 1889 | default: |
@@ -1990,10 +1990,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1990 | 1990 | ||
1991 | switch (cmd) { | 1991 | switch (cmd) { |
1992 | case IP6T_SO_GET_INFO: | 1992 | case IP6T_SO_GET_INFO: |
1993 | ret = get_info(sk->sk_net, user, len, 1); | 1993 | ret = get_info(sock_net(sk), user, len, 1); |
1994 | break; | 1994 | break; |
1995 | case IP6T_SO_GET_ENTRIES: | 1995 | case IP6T_SO_GET_ENTRIES: |
1996 | ret = compat_get_entries(sk->sk_net, user, len); | 1996 | ret = compat_get_entries(sock_net(sk), user, len); |
1997 | break; | 1997 | break; |
1998 | default: | 1998 | default: |
1999 | ret = do_ip6t_get_ctl(sk, cmd, user, len); | 1999 | ret = do_ip6t_get_ctl(sk, cmd, user, len); |
@@ -2012,11 +2012,11 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2012 | 2012 | ||
2013 | switch (cmd) { | 2013 | switch (cmd) { |
2014 | case IP6T_SO_SET_REPLACE: | 2014 | case IP6T_SO_SET_REPLACE: |
2015 | ret = do_replace(sk->sk_net, user, len); | 2015 | ret = do_replace(sock_net(sk), user, len); |
2016 | break; | 2016 | break; |
2017 | 2017 | ||
2018 | case IP6T_SO_SET_ADD_COUNTERS: | 2018 | case IP6T_SO_SET_ADD_COUNTERS: |
2019 | ret = do_add_counters(sk->sk_net, user, len, 0); | 2019 | ret = do_add_counters(sock_net(sk), user, len, 0); |
2020 | break; | 2020 | break; |
2021 | 2021 | ||
2022 | default: | 2022 | default: |
@@ -2037,11 +2037,11 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2037 | 2037 | ||
2038 | switch (cmd) { | 2038 | switch (cmd) { |
2039 | case IP6T_SO_GET_INFO: | 2039 | case IP6T_SO_GET_INFO: |
2040 | ret = get_info(sk->sk_net, user, len, 0); | 2040 | ret = get_info(sock_net(sk), user, len, 0); |
2041 | break; | 2041 | break; |
2042 | 2042 | ||
2043 | case IP6T_SO_GET_ENTRIES: | 2043 | case IP6T_SO_GET_ENTRIES: |
2044 | ret = get_entries(sk->sk_net, user, len); | 2044 | ret = get_entries(sock_net(sk), user, len); |
2045 | break; | 2045 | break; |
2046 | 2046 | ||
2047 | case IP6T_SO_GET_REVISION_MATCH: | 2047 | case IP6T_SO_GET_REVISION_MATCH: |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b23baa635fe0..baf829075f6f 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -93,7 +93,7 @@ static void send_reset(struct sk_buff *oldskb) | |||
93 | fl.fl_ip_sport = otcph.dest; | 93 | fl.fl_ip_sport = otcph.dest; |
94 | fl.fl_ip_dport = otcph.source; | 94 | fl.fl_ip_dport = otcph.source; |
95 | security_skb_classify_flow(oldskb, &fl); | 95 | security_skb_classify_flow(oldskb, &fl); |
96 | dst = ip6_route_output(NULL, &fl); | 96 | dst = ip6_route_output(&init_net, NULL, &fl); |
97 | if (dst == NULL) | 97 | if (dst == NULL) |
98 | return; | 98 | return; |
99 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) | 99 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) |
@@ -177,7 +177,7 @@ reject_tg6(struct sk_buff *skb, const struct net_device *in, | |||
177 | { | 177 | { |
178 | const struct ip6t_reject_info *reject = targinfo; | 178 | const struct ip6t_reject_info *reject = targinfo; |
179 | 179 | ||
180 | pr_debug("%s: medium point\n", __FUNCTION__); | 180 | pr_debug("%s: medium point\n", __func__); |
181 | /* WARNING: This code causes reentry within ip6tables. | 181 | /* WARNING: This code causes reentry within ip6tables. |
182 | This means that the ip6tables jump stack is now crap. We | 182 | This means that the ip6tables jump stack is now crap. We |
183 | must return an absolute verdict. --RR */ | 183 | must return an absolute verdict. --RR */ |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 24c0d03095bf..9e5f305b2022 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -185,7 +185,7 @@ static void nf_ct_frag6_expire(unsigned long data) | |||
185 | 185 | ||
186 | spin_lock(&fq->q.lock); | 186 | spin_lock(&fq->q.lock); |
187 | 187 | ||
188 | if (fq->q.last_in & COMPLETE) | 188 | if (fq->q.last_in & INET_FRAG_COMPLETE) |
189 | goto out; | 189 | goto out; |
190 | 190 | ||
191 | fq_kill(fq); | 191 | fq_kill(fq); |
@@ -227,7 +227,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
227 | struct sk_buff *prev, *next; | 227 | struct sk_buff *prev, *next; |
228 | int offset, end; | 228 | int offset, end; |
229 | 229 | ||
230 | if (fq->q.last_in & COMPLETE) { | 230 | if (fq->q.last_in & INET_FRAG_COMPLETE) { |
231 | pr_debug("Allready completed\n"); | 231 | pr_debug("Allready completed\n"); |
232 | goto err; | 232 | goto err; |
233 | } | 233 | } |
@@ -254,11 +254,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
254 | * or have different end, the segment is corrupted. | 254 | * or have different end, the segment is corrupted. |
255 | */ | 255 | */ |
256 | if (end < fq->q.len || | 256 | if (end < fq->q.len || |
257 | ((fq->q.last_in & LAST_IN) && end != fq->q.len)) { | 257 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) { |
258 | pr_debug("already received last fragment\n"); | 258 | pr_debug("already received last fragment\n"); |
259 | goto err; | 259 | goto err; |
260 | } | 260 | } |
261 | fq->q.last_in |= LAST_IN; | 261 | fq->q.last_in |= INET_FRAG_LAST_IN; |
262 | fq->q.len = end; | 262 | fq->q.len = end; |
263 | } else { | 263 | } else { |
264 | /* Check if the fragment is rounded to 8 bytes. | 264 | /* Check if the fragment is rounded to 8 bytes. |
@@ -273,7 +273,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
273 | } | 273 | } |
274 | if (end > fq->q.len) { | 274 | if (end > fq->q.len) { |
275 | /* Some bits beyond end -> corruption. */ | 275 | /* Some bits beyond end -> corruption. */ |
276 | if (fq->q.last_in & LAST_IN) { | 276 | if (fq->q.last_in & INET_FRAG_LAST_IN) { |
277 | pr_debug("last packet already reached.\n"); | 277 | pr_debug("last packet already reached.\n"); |
278 | goto err; | 278 | goto err; |
279 | } | 279 | } |
@@ -385,7 +385,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
385 | */ | 385 | */ |
386 | if (offset == 0) { | 386 | if (offset == 0) { |
387 | fq->nhoffset = nhoff; | 387 | fq->nhoffset = nhoff; |
388 | fq->q.last_in |= FIRST_IN; | 388 | fq->q.last_in |= INET_FRAG_FIRST_IN; |
389 | } | 389 | } |
390 | write_lock(&nf_frags.lock); | 390 | write_lock(&nf_frags.lock); |
391 | list_move_tail(&fq->q.lru_list, &nf_init_frags.lru_list); | 391 | list_move_tail(&fq->q.lru_list, &nf_init_frags.lru_list); |
@@ -647,7 +647,8 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
647 | goto ret_orig; | 647 | goto ret_orig; |
648 | } | 648 | } |
649 | 649 | ||
650 | if (fq->q.last_in == (FIRST_IN|LAST_IN) && fq->q.meat == fq->q.len) { | 650 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
651 | fq->q.meat == fq->q.len) { | ||
651 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 652 | ret_skb = nf_ct_frag6_reasm(fq, dev); |
652 | if (ret_skb == NULL) | 653 | if (ret_skb == NULL) |
653 | pr_debug("Can't reassemble fragmented packets\n"); | 654 | pr_debug("Can't reassemble fragmented packets\n"); |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 199ef379e501..ca8b82f96fe5 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -35,16 +35,18 @@ static struct proc_dir_entry *proc_net_devsnmp6; | |||
35 | 35 | ||
36 | static int sockstat6_seq_show(struct seq_file *seq, void *v) | 36 | static int sockstat6_seq_show(struct seq_file *seq, void *v) |
37 | { | 37 | { |
38 | struct net *net = seq->private; | ||
39 | |||
38 | seq_printf(seq, "TCP6: inuse %d\n", | 40 | seq_printf(seq, "TCP6: inuse %d\n", |
39 | sock_prot_inuse_get(&tcpv6_prot)); | 41 | sock_prot_inuse_get(net, &tcpv6_prot)); |
40 | seq_printf(seq, "UDP6: inuse %d\n", | 42 | seq_printf(seq, "UDP6: inuse %d\n", |
41 | sock_prot_inuse_get(&udpv6_prot)); | 43 | sock_prot_inuse_get(net, &udpv6_prot)); |
42 | seq_printf(seq, "UDPLITE6: inuse %d\n", | 44 | seq_printf(seq, "UDPLITE6: inuse %d\n", |
43 | sock_prot_inuse_get(&udplitev6_prot)); | 45 | sock_prot_inuse_get(net, &udplitev6_prot)); |
44 | seq_printf(seq, "RAW6: inuse %d\n", | 46 | seq_printf(seq, "RAW6: inuse %d\n", |
45 | sock_prot_inuse_get(&rawv6_prot)); | 47 | sock_prot_inuse_get(net, &rawv6_prot)); |
46 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", | 48 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", |
47 | ip6_frag_nqueues(&init_net), ip6_frag_mem(&init_net)); | 49 | ip6_frag_nqueues(net), ip6_frag_mem(net)); |
48 | return 0; | 50 | return 0; |
49 | } | 51 | } |
50 | 52 | ||
@@ -183,7 +185,32 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) | |||
183 | 185 | ||
184 | static int sockstat6_seq_open(struct inode *inode, struct file *file) | 186 | static int sockstat6_seq_open(struct inode *inode, struct file *file) |
185 | { | 187 | { |
186 | return single_open(file, sockstat6_seq_show, NULL); | 188 | int err; |
189 | struct net *net; | ||
190 | |||
191 | err = -ENXIO; | ||
192 | net = get_proc_net(inode); | ||
193 | if (net == NULL) | ||
194 | goto err_net; | ||
195 | |||
196 | err = single_open(file, sockstat6_seq_show, net); | ||
197 | if (err < 0) | ||
198 | goto err_open; | ||
199 | |||
200 | return 0; | ||
201 | |||
202 | err_open: | ||
203 | put_net(net); | ||
204 | err_net: | ||
205 | return err; | ||
206 | } | ||
207 | |||
208 | static int sockstat6_seq_release(struct inode *inode, struct file *file) | ||
209 | { | ||
210 | struct net *net = ((struct seq_file *)file->private_data)->private; | ||
211 | |||
212 | put_net(net); | ||
213 | return single_release(inode, file); | ||
187 | } | 214 | } |
188 | 215 | ||
189 | static const struct file_operations sockstat6_seq_fops = { | 216 | static const struct file_operations sockstat6_seq_fops = { |
@@ -191,7 +218,7 @@ static const struct file_operations sockstat6_seq_fops = { | |||
191 | .open = sockstat6_seq_open, | 218 | .open = sockstat6_seq_open, |
192 | .read = seq_read, | 219 | .read = seq_read, |
193 | .llseek = seq_lseek, | 220 | .llseek = seq_lseek, |
194 | .release = single_release, | 221 | .release = sockstat6_seq_release, |
195 | }; | 222 | }; |
196 | 223 | ||
197 | static int snmp6_seq_open(struct inode *inode, struct file *file) | 224 | static int snmp6_seq_open(struct inode *inode, struct file *file) |
@@ -214,6 +241,9 @@ int snmp6_register_dev(struct inet6_dev *idev) | |||
214 | if (!idev || !idev->dev) | 241 | if (!idev || !idev->dev) |
215 | return -EINVAL; | 242 | return -EINVAL; |
216 | 243 | ||
244 | if (dev_net(idev->dev) != &init_net) | ||
245 | return 0; | ||
246 | |||
217 | if (!proc_net_devsnmp6) | 247 | if (!proc_net_devsnmp6) |
218 | return -ENOENT; | 248 | return -ENOENT; |
219 | 249 | ||
@@ -240,27 +270,45 @@ int snmp6_unregister_dev(struct inet6_dev *idev) | |||
240 | return 0; | 270 | return 0; |
241 | } | 271 | } |
242 | 272 | ||
273 | static int ipv6_proc_init_net(struct net *net) | ||
274 | { | ||
275 | if (!proc_net_fops_create(net, "sockstat6", S_IRUGO, | ||
276 | &sockstat6_seq_fops)) | ||
277 | return -ENOMEM; | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static void ipv6_proc_exit_net(struct net *net) | ||
282 | { | ||
283 | proc_net_remove(net, "sockstat6"); | ||
284 | } | ||
285 | |||
286 | static struct pernet_operations ipv6_proc_ops = { | ||
287 | .init = ipv6_proc_init_net, | ||
288 | .exit = ipv6_proc_exit_net, | ||
289 | }; | ||
290 | |||
243 | int __init ipv6_misc_proc_init(void) | 291 | int __init ipv6_misc_proc_init(void) |
244 | { | 292 | { |
245 | int rc = 0; | 293 | int rc = 0; |
246 | 294 | ||
295 | if (register_pernet_subsys(&ipv6_proc_ops)) | ||
296 | goto proc_net_fail; | ||
297 | |||
247 | if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops)) | 298 | if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops)) |
248 | goto proc_snmp6_fail; | 299 | goto proc_snmp6_fail; |
249 | 300 | ||
250 | proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net); | 301 | proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net); |
251 | if (!proc_net_devsnmp6) | 302 | if (!proc_net_devsnmp6) |
252 | goto proc_dev_snmp6_fail; | 303 | goto proc_dev_snmp6_fail; |
253 | |||
254 | if (!proc_net_fops_create(&init_net, "sockstat6", S_IRUGO, &sockstat6_seq_fops)) | ||
255 | goto proc_sockstat6_fail; | ||
256 | out: | 304 | out: |
257 | return rc; | 305 | return rc; |
258 | 306 | ||
259 | proc_sockstat6_fail: | ||
260 | proc_net_remove(&init_net, "dev_snmp6"); | ||
261 | proc_dev_snmp6_fail: | 307 | proc_dev_snmp6_fail: |
262 | proc_net_remove(&init_net, "snmp6"); | 308 | proc_net_remove(&init_net, "snmp6"); |
263 | proc_snmp6_fail: | 309 | proc_snmp6_fail: |
310 | unregister_pernet_subsys(&ipv6_proc_ops); | ||
311 | proc_net_fail: | ||
264 | rc = -ENOMEM; | 312 | rc = -ENOMEM; |
265 | goto out; | 313 | goto out; |
266 | } | 314 | } |
@@ -270,5 +318,6 @@ void ipv6_misc_proc_exit(void) | |||
270 | proc_net_remove(&init_net, "sockstat6"); | 318 | proc_net_remove(&init_net, "sockstat6"); |
271 | proc_net_remove(&init_net, "dev_snmp6"); | 319 | proc_net_remove(&init_net, "dev_snmp6"); |
272 | proc_net_remove(&init_net, "snmp6"); | 320 | proc_net_remove(&init_net, "snmp6"); |
321 | unregister_pernet_subsys(&ipv6_proc_ops); | ||
273 | } | 322 | } |
274 | 323 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 0a6fbc1d1a50..6193b124cbc7 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 53 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
54 | #include <net/mip6.h> | 54 | #include <net/mip6.h> |
55 | #endif | 55 | #endif |
56 | #include <linux/mroute6.h> | ||
56 | 57 | ||
57 | #include <net/raw.h> | 58 | #include <net/raw.h> |
58 | #include <net/rawv6.h> | 59 | #include <net/rawv6.h> |
@@ -62,20 +63,9 @@ | |||
62 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
63 | 64 | ||
64 | static struct raw_hashinfo raw_v6_hashinfo = { | 65 | static struct raw_hashinfo raw_v6_hashinfo = { |
65 | .lock = __RW_LOCK_UNLOCKED(), | 66 | .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock), |
66 | }; | 67 | }; |
67 | 68 | ||
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, | 69 | static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, |
80 | unsigned short num, struct in6_addr *loc_addr, | 70 | unsigned short num, struct in6_addr *loc_addr, |
81 | struct in6_addr *rmt_addr, int dif) | 71 | struct in6_addr *rmt_addr, int dif) |
@@ -87,7 +77,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, | |||
87 | if (inet_sk(sk)->num == num) { | 77 | if (inet_sk(sk)->num == num) { |
88 | struct ipv6_pinfo *np = inet6_sk(sk); | 78 | struct ipv6_pinfo *np = inet6_sk(sk); |
89 | 79 | ||
90 | if (sk->sk_net != net) | 80 | if (!net_eq(sock_net(sk), net)) |
91 | continue; | 81 | continue; |
92 | 82 | ||
93 | if (!ipv6_addr_any(&np->daddr) && | 83 | if (!ipv6_addr_any(&np->daddr) && |
@@ -179,15 +169,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
179 | read_lock(&raw_v6_hashinfo.lock); | 169 | read_lock(&raw_v6_hashinfo.lock); |
180 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); | 170 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); |
181 | 171 | ||
182 | /* | ||
183 | * The first socket found will be delivered after | ||
184 | * delivery to transport protocols. | ||
185 | */ | ||
186 | |||
187 | if (sk == NULL) | 172 | if (sk == NULL) |
188 | goto out; | 173 | goto out; |
189 | 174 | ||
190 | net = skb->dev->nd_net; | 175 | net = dev_net(skb->dev); |
191 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); | 176 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); |
192 | 177 | ||
193 | while (sk) { | 178 | while (sk) { |
@@ -291,7 +276,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
291 | if (!sk->sk_bound_dev_if) | 276 | if (!sk->sk_bound_dev_if) |
292 | goto out; | 277 | goto out; |
293 | 278 | ||
294 | dev = dev_get_by_index(sk->sk_net, sk->sk_bound_dev_if); | 279 | dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); |
295 | if (!dev) { | 280 | if (!dev) { |
296 | err = -ENODEV; | 281 | err = -ENODEV; |
297 | goto out; | 282 | goto out; |
@@ -304,7 +289,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
304 | v4addr = LOOPBACK4_IPV6; | 289 | v4addr = LOOPBACK4_IPV6; |
305 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 290 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
306 | err = -EADDRNOTAVAIL; | 291 | err = -EADDRNOTAVAIL; |
307 | if (!ipv6_chk_addr(sk->sk_net, &addr->sin6_addr, | 292 | if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, |
308 | dev, 0)) { | 293 | dev, 0)) { |
309 | if (dev) | 294 | if (dev) |
310 | dev_put(dev); | 295 | dev_put(dev); |
@@ -372,11 +357,11 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
372 | read_lock(&raw_v6_hashinfo.lock); | 357 | read_lock(&raw_v6_hashinfo.lock); |
373 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); | 358 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); |
374 | if (sk != NULL) { | 359 | if (sk != NULL) { |
375 | struct ipv6hdr *hdr = (struct ipv6hdr *) skb->data; | 360 | /* Note: ipv6_hdr(skb) != skb->data */ |
376 | 361 | struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data; | |
377 | saddr = &hdr->saddr; | 362 | saddr = &ip6h->saddr; |
378 | daddr = &hdr->daddr; | 363 | daddr = &ip6h->daddr; |
379 | net = skb->dev->nd_net; | 364 | net = dev_net(skb->dev); |
380 | 365 | ||
381 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, | 366 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, |
382 | IP6CB(skb)->iif))) { | 367 | IP6CB(skb)->iif))) { |
@@ -822,15 +807,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
822 | fl.fl6_flowlabel = np->flow_label; | 807 | fl.fl6_flowlabel = np->flow_label; |
823 | } | 808 | } |
824 | 809 | ||
825 | if (ipv6_addr_any(daddr)) { | ||
826 | /* | ||
827 | * unspecified destination address | ||
828 | * treated as error... is this correct ? | ||
829 | */ | ||
830 | fl6_sock_release(flowlabel); | ||
831 | return(-EINVAL); | ||
832 | } | ||
833 | |||
834 | if (fl.oif == 0) | 810 | if (fl.oif == 0) |
835 | fl.oif = sk->sk_bound_dev_if; | 811 | fl.oif = sk->sk_bound_dev_if; |
836 | 812 | ||
@@ -863,7 +839,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
863 | if (err) | 839 | if (err) |
864 | goto out; | 840 | goto out; |
865 | 841 | ||
866 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 842 | if (!ipv6_addr_any(daddr)) |
843 | ipv6_addr_copy(&fl.fl6_dst, daddr); | ||
844 | else | ||
845 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
867 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 846 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
868 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 847 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
869 | 848 | ||
@@ -898,9 +877,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
898 | else | 877 | else |
899 | hlimit = np->hop_limit; | 878 | hlimit = np->hop_limit; |
900 | if (hlimit < 0) | 879 | if (hlimit < 0) |
901 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 880 | hlimit = ip6_dst_hoplimit(dst); |
902 | if (hlimit < 0) | ||
903 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
904 | } | 881 | } |
905 | 882 | ||
906 | if (tclass < 0) { | 883 | if (tclass < 0) { |
@@ -1155,7 +1132,11 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
1155 | } | 1132 | } |
1156 | 1133 | ||
1157 | default: | 1134 | default: |
1135 | #ifdef CONFIG_IPV6_MROUTE | ||
1136 | return ip6mr_ioctl(sk, cmd, (void __user *)arg); | ||
1137 | #else | ||
1158 | return -ENOIOCTLCMD; | 1138 | return -ENOIOCTLCMD; |
1139 | #endif | ||
1159 | } | 1140 | } |
1160 | } | 1141 | } |
1161 | 1142 | ||
@@ -1163,7 +1144,7 @@ static void rawv6_close(struct sock *sk, long timeout) | |||
1163 | { | 1144 | { |
1164 | if (inet_sk(sk)->num == IPPROTO_RAW) | 1145 | if (inet_sk(sk)->num == IPPROTO_RAW) |
1165 | ip6_ra_control(sk, -1, NULL); | 1146 | ip6_ra_control(sk, -1, NULL); |
1166 | 1147 | ip6mr_sk_done(sk); | |
1167 | sk_common_release(sk); | 1148 | sk_common_release(sk); |
1168 | } | 1149 | } |
1169 | 1150 | ||
@@ -1186,8 +1167,6 @@ static int rawv6_init_sk(struct sock *sk) | |||
1186 | return(0); | 1167 | return(0); |
1187 | } | 1168 | } |
1188 | 1169 | ||
1189 | DEFINE_PROTO_INUSE(rawv6) | ||
1190 | |||
1191 | struct proto rawv6_prot = { | 1170 | struct proto rawv6_prot = { |
1192 | .name = "RAWv6", | 1171 | .name = "RAWv6", |
1193 | .owner = THIS_MODULE, | 1172 | .owner = THIS_MODULE, |
@@ -1203,14 +1182,14 @@ struct proto rawv6_prot = { | |||
1203 | .recvmsg = rawv6_recvmsg, | 1182 | .recvmsg = rawv6_recvmsg, |
1204 | .bind = rawv6_bind, | 1183 | .bind = rawv6_bind, |
1205 | .backlog_rcv = rawv6_rcv_skb, | 1184 | .backlog_rcv = rawv6_rcv_skb, |
1206 | .hash = raw_v6_hash, | 1185 | .hash = raw_hash_sk, |
1207 | .unhash = raw_v6_unhash, | 1186 | .unhash = raw_unhash_sk, |
1208 | .obj_size = sizeof(struct raw6_sock), | 1187 | .obj_size = sizeof(struct raw6_sock), |
1188 | .h.raw_hash = &raw_v6_hashinfo, | ||
1209 | #ifdef CONFIG_COMPAT | 1189 | #ifdef CONFIG_COMPAT |
1210 | .compat_setsockopt = compat_rawv6_setsockopt, | 1190 | .compat_setsockopt = compat_rawv6_setsockopt, |
1211 | .compat_getsockopt = compat_rawv6_getsockopt, | 1191 | .compat_getsockopt = compat_rawv6_getsockopt, |
1212 | #endif | 1192 | #endif |
1213 | REF_PROTO_INUSE(rawv6) | ||
1214 | }; | 1193 | }; |
1215 | 1194 | ||
1216 | #ifdef CONFIG_PROC_FS | 1195 | #ifdef CONFIG_PROC_FS |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index f936d045a39d..7b247e3a16fe 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -202,7 +202,7 @@ static void ip6_frag_expire(unsigned long data) | |||
202 | 202 | ||
203 | spin_lock(&fq->q.lock); | 203 | spin_lock(&fq->q.lock); |
204 | 204 | ||
205 | if (fq->q.last_in & COMPLETE) | 205 | if (fq->q.last_in & INET_FRAG_COMPLETE) |
206 | goto out; | 206 | goto out; |
207 | 207 | ||
208 | fq_kill(fq); | 208 | fq_kill(fq); |
@@ -217,7 +217,7 @@ static void ip6_frag_expire(unsigned long data) | |||
217 | rcu_read_unlock(); | 217 | rcu_read_unlock(); |
218 | 218 | ||
219 | /* Don't send error if the first segment did not arrive. */ | 219 | /* Don't send error if the first segment did not arrive. */ |
220 | if (!(fq->q.last_in&FIRST_IN) || !fq->q.fragments) | 220 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) |
221 | goto out; | 221 | goto out; |
222 | 222 | ||
223 | /* | 223 | /* |
@@ -265,7 +265,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
265 | struct net_device *dev; | 265 | struct net_device *dev; |
266 | int offset, end; | 266 | int offset, end; |
267 | 267 | ||
268 | if (fq->q.last_in & COMPLETE) | 268 | if (fq->q.last_in & INET_FRAG_COMPLETE) |
269 | goto err; | 269 | goto err; |
270 | 270 | ||
271 | offset = ntohs(fhdr->frag_off) & ~0x7; | 271 | offset = ntohs(fhdr->frag_off) & ~0x7; |
@@ -294,9 +294,9 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
294 | * or have different end, the segment is corrupted. | 294 | * or have different end, the segment is corrupted. |
295 | */ | 295 | */ |
296 | if (end < fq->q.len || | 296 | if (end < fq->q.len || |
297 | ((fq->q.last_in & LAST_IN) && end != fq->q.len)) | 297 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) |
298 | goto err; | 298 | goto err; |
299 | fq->q.last_in |= LAST_IN; | 299 | fq->q.last_in |= INET_FRAG_LAST_IN; |
300 | fq->q.len = end; | 300 | fq->q.len = end; |
301 | } else { | 301 | } else { |
302 | /* Check if the fragment is rounded to 8 bytes. | 302 | /* Check if the fragment is rounded to 8 bytes. |
@@ -314,7 +314,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
314 | } | 314 | } |
315 | if (end > fq->q.len) { | 315 | if (end > fq->q.len) { |
316 | /* Some bits beyond end -> corruption. */ | 316 | /* Some bits beyond end -> corruption. */ |
317 | if (fq->q.last_in & LAST_IN) | 317 | if (fq->q.last_in & INET_FRAG_LAST_IN) |
318 | goto err; | 318 | goto err; |
319 | fq->q.len = end; | 319 | fq->q.len = end; |
320 | } | 320 | } |
@@ -417,10 +417,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
417 | */ | 417 | */ |
418 | if (offset == 0) { | 418 | if (offset == 0) { |
419 | fq->nhoffset = nhoff; | 419 | fq->nhoffset = nhoff; |
420 | fq->q.last_in |= FIRST_IN; | 420 | fq->q.last_in |= INET_FRAG_FIRST_IN; |
421 | } | 421 | } |
422 | 422 | ||
423 | if (fq->q.last_in == (FIRST_IN | LAST_IN) && fq->q.meat == fq->q.len) | 423 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
424 | fq->q.meat == fq->q.len) | ||
424 | return ip6_frag_reasm(fq, prev, dev); | 425 | return ip6_frag_reasm(fq, prev, dev); |
425 | 426 | ||
426 | write_lock(&ip6_frags.lock); | 427 | write_lock(&ip6_frags.lock); |
@@ -600,7 +601,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
600 | return 1; | 601 | return 1; |
601 | } | 602 | } |
602 | 603 | ||
603 | net = skb->dev->nd_net; | 604 | net = dev_net(skb->dev); |
604 | if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) | 605 | if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) |
605 | ip6_evictor(net, ip6_dst_idev(skb->dst)); | 606 | ip6_evictor(net, ip6_dst_idev(skb->dst)); |
606 | 607 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e8b241cb60bc..6293cb91ed1d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -36,10 +36,12 @@ | |||
36 | #include <linux/route.h> | 36 | #include <linux/route.h> |
37 | #include <linux/netdevice.h> | 37 | #include <linux/netdevice.h> |
38 | #include <linux/in6.h> | 38 | #include <linux/in6.h> |
39 | #include <linux/mroute6.h> | ||
39 | #include <linux/init.h> | 40 | #include <linux/init.h> |
40 | #include <linux/if_arp.h> | 41 | #include <linux/if_arp.h> |
41 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
42 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/nsproxy.h> | ||
43 | #include <net/net_namespace.h> | 45 | #include <net/net_namespace.h> |
44 | #include <net/snmp.h> | 46 | #include <net/snmp.h> |
45 | #include <net/ipv6.h> | 47 | #include <net/ipv6.h> |
@@ -87,14 +89,16 @@ static void ip6_link_failure(struct sk_buff *skb); | |||
87 | static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); | 89 | static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); |
88 | 90 | ||
89 | #ifdef CONFIG_IPV6_ROUTE_INFO | 91 | #ifdef CONFIG_IPV6_ROUTE_INFO |
90 | static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, | 92 | static struct rt6_info *rt6_add_route_info(struct net *net, |
93 | struct in6_addr *prefix, int prefixlen, | ||
91 | struct in6_addr *gwaddr, int ifindex, | 94 | struct in6_addr *gwaddr, int ifindex, |
92 | unsigned pref); | 95 | unsigned pref); |
93 | static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, | 96 | static struct rt6_info *rt6_get_route_info(struct net *net, |
97 | struct in6_addr *prefix, int prefixlen, | ||
94 | struct in6_addr *gwaddr, int ifindex); | 98 | struct in6_addr *gwaddr, int ifindex); |
95 | #endif | 99 | #endif |
96 | 100 | ||
97 | static struct dst_ops ip6_dst_ops = { | 101 | static struct dst_ops ip6_dst_ops_template = { |
98 | .family = AF_INET6, | 102 | .family = AF_INET6, |
99 | .protocol = __constant_htons(ETH_P_IPV6), | 103 | .protocol = __constant_htons(ETH_P_IPV6), |
100 | .gc = ip6_dst_gc, | 104 | .gc = ip6_dst_gc, |
@@ -124,7 +128,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
124 | .entries = ATOMIC_INIT(0), | 128 | .entries = ATOMIC_INIT(0), |
125 | }; | 129 | }; |
126 | 130 | ||
127 | struct rt6_info ip6_null_entry = { | 131 | static struct rt6_info ip6_null_entry_template = { |
128 | .u = { | 132 | .u = { |
129 | .dst = { | 133 | .dst = { |
130 | .__refcnt = ATOMIC_INIT(1), | 134 | .__refcnt = ATOMIC_INIT(1), |
@@ -134,8 +138,6 @@ struct rt6_info ip6_null_entry = { | |||
134 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 138 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
135 | .input = ip6_pkt_discard, | 139 | .input = ip6_pkt_discard, |
136 | .output = ip6_pkt_discard_out, | 140 | .output = ip6_pkt_discard_out, |
137 | .ops = &ip6_dst_ops, | ||
138 | .path = (struct dst_entry*)&ip6_null_entry, | ||
139 | } | 141 | } |
140 | }, | 142 | }, |
141 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 143 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
@@ -148,7 +150,7 @@ struct rt6_info ip6_null_entry = { | |||
148 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 150 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
149 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 151 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
150 | 152 | ||
151 | struct rt6_info ip6_prohibit_entry = { | 153 | struct rt6_info ip6_prohibit_entry_template = { |
152 | .u = { | 154 | .u = { |
153 | .dst = { | 155 | .dst = { |
154 | .__refcnt = ATOMIC_INIT(1), | 156 | .__refcnt = ATOMIC_INIT(1), |
@@ -158,8 +160,6 @@ struct rt6_info ip6_prohibit_entry = { | |||
158 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 160 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
159 | .input = ip6_pkt_prohibit, | 161 | .input = ip6_pkt_prohibit, |
160 | .output = ip6_pkt_prohibit_out, | 162 | .output = ip6_pkt_prohibit_out, |
161 | .ops = &ip6_dst_ops, | ||
162 | .path = (struct dst_entry*)&ip6_prohibit_entry, | ||
163 | } | 163 | } |
164 | }, | 164 | }, |
165 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 165 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
@@ -167,7 +167,7 @@ struct rt6_info ip6_prohibit_entry = { | |||
167 | .rt6i_ref = ATOMIC_INIT(1), | 167 | .rt6i_ref = ATOMIC_INIT(1), |
168 | }; | 168 | }; |
169 | 169 | ||
170 | struct rt6_info ip6_blk_hole_entry = { | 170 | static struct rt6_info ip6_blk_hole_entry_template = { |
171 | .u = { | 171 | .u = { |
172 | .dst = { | 172 | .dst = { |
173 | .__refcnt = ATOMIC_INIT(1), | 173 | .__refcnt = ATOMIC_INIT(1), |
@@ -177,8 +177,6 @@ struct rt6_info ip6_blk_hole_entry = { | |||
177 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 177 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
178 | .input = dst_discard, | 178 | .input = dst_discard, |
179 | .output = dst_discard, | 179 | .output = dst_discard, |
180 | .ops = &ip6_dst_ops, | ||
181 | .path = (struct dst_entry*)&ip6_blk_hole_entry, | ||
182 | } | 180 | } |
183 | }, | 181 | }, |
184 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 182 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
@@ -189,9 +187,9 @@ struct rt6_info ip6_blk_hole_entry = { | |||
189 | #endif | 187 | #endif |
190 | 188 | ||
191 | /* allocate dst with ip6_dst_ops */ | 189 | /* allocate dst with ip6_dst_ops */ |
192 | static __inline__ struct rt6_info *ip6_dst_alloc(void) | 190 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) |
193 | { | 191 | { |
194 | return (struct rt6_info *)dst_alloc(&ip6_dst_ops); | 192 | return (struct rt6_info *)dst_alloc(ops); |
195 | } | 193 | } |
196 | 194 | ||
197 | static void ip6_dst_destroy(struct dst_entry *dst) | 195 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -211,7 +209,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
211 | struct rt6_info *rt = (struct rt6_info *)dst; | 209 | struct rt6_info *rt = (struct rt6_info *)dst; |
212 | struct inet6_dev *idev = rt->rt6i_idev; | 210 | struct inet6_dev *idev = rt->rt6i_idev; |
213 | struct net_device *loopback_dev = | 211 | struct net_device *loopback_dev = |
214 | dev->nd_net->loopback_dev; | 212 | dev_net(dev)->loopback_dev; |
215 | 213 | ||
216 | if (dev != loopback_dev && idev != NULL && idev->dev == dev) { | 214 | if (dev != loopback_dev && idev != NULL && idev->dev == dev) { |
217 | struct inet6_dev *loopback_idev = | 215 | struct inet6_dev *loopback_idev = |
@@ -239,7 +237,8 @@ static inline int rt6_need_strict(struct in6_addr *daddr) | |||
239 | * Route lookup. Any table->tb6_lock is implied. | 237 | * Route lookup. Any table->tb6_lock is implied. |
240 | */ | 238 | */ |
241 | 239 | ||
242 | static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | 240 | static inline struct rt6_info *rt6_device_match(struct net *net, |
241 | struct rt6_info *rt, | ||
243 | int oif, | 242 | int oif, |
244 | int strict) | 243 | int strict) |
245 | { | 244 | { |
@@ -268,7 +267,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | |||
268 | return local; | 267 | return local; |
269 | 268 | ||
270 | if (strict) | 269 | if (strict) |
271 | return &ip6_null_entry; | 270 | return net->ipv6.ip6_null_entry; |
272 | } | 271 | } |
273 | return rt; | 272 | return rt; |
274 | } | 273 | } |
@@ -409,9 +408,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) | 408 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) |
410 | { | 409 | { |
411 | struct rt6_info *match, *rt0; | 410 | struct rt6_info *match, *rt0; |
411 | struct net *net; | ||
412 | 412 | ||
413 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", | 413 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", |
414 | __FUNCTION__, fn->leaf, oif); | 414 | __func__, fn->leaf, oif); |
415 | 415 | ||
416 | rt0 = fn->rr_ptr; | 416 | rt0 = fn->rr_ptr; |
417 | if (!rt0) | 417 | if (!rt0) |
@@ -432,15 +432,17 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | RT6_TRACE("%s() => %p\n", | 434 | RT6_TRACE("%s() => %p\n", |
435 | __FUNCTION__, match); | 435 | __func__, match); |
436 | 436 | ||
437 | return (match ? match : &ip6_null_entry); | 437 | net = dev_net(rt0->rt6i_dev); |
438 | return (match ? match : net->ipv6.ip6_null_entry); | ||
438 | } | 439 | } |
439 | 440 | ||
440 | #ifdef CONFIG_IPV6_ROUTE_INFO | 441 | #ifdef CONFIG_IPV6_ROUTE_INFO |
441 | int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | 442 | int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, |
442 | struct in6_addr *gwaddr) | 443 | struct in6_addr *gwaddr) |
443 | { | 444 | { |
445 | struct net *net = dev_net(dev); | ||
444 | struct route_info *rinfo = (struct route_info *) opt; | 446 | struct route_info *rinfo = (struct route_info *) opt; |
445 | struct in6_addr prefix_buf, *prefix; | 447 | struct in6_addr prefix_buf, *prefix; |
446 | unsigned int pref; | 448 | unsigned int pref; |
@@ -488,7 +490,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
488 | prefix = &prefix_buf; | 490 | prefix = &prefix_buf; |
489 | } | 491 | } |
490 | 492 | ||
491 | rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex); | 493 | rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr, |
494 | dev->ifindex); | ||
492 | 495 | ||
493 | if (rt && !lifetime) { | 496 | if (rt && !lifetime) { |
494 | ip6_del_rt(rt); | 497 | ip6_del_rt(rt); |
@@ -496,7 +499,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
496 | } | 499 | } |
497 | 500 | ||
498 | if (!rt && lifetime) | 501 | if (!rt && lifetime) |
499 | rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex, | 502 | rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex, |
500 | pref); | 503 | pref); |
501 | else if (rt) | 504 | else if (rt) |
502 | rt->rt6i_flags = RTF_ROUTEINFO | | 505 | rt->rt6i_flags = RTF_ROUTEINFO | |
@@ -515,9 +518,9 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
515 | } | 518 | } |
516 | #endif | 519 | #endif |
517 | 520 | ||
518 | #define BACKTRACK(saddr) \ | 521 | #define BACKTRACK(__net, saddr) \ |
519 | do { \ | 522 | do { \ |
520 | if (rt == &ip6_null_entry) { \ | 523 | if (rt == __net->ipv6.ip6_null_entry) { \ |
521 | struct fib6_node *pn; \ | 524 | struct fib6_node *pn; \ |
522 | while (1) { \ | 525 | while (1) { \ |
523 | if (fn->fn_flags & RTN_TL_ROOT) \ | 526 | if (fn->fn_flags & RTN_TL_ROOT) \ |
@@ -533,7 +536,8 @@ do { \ | |||
533 | } \ | 536 | } \ |
534 | } while(0) | 537 | } while(0) |
535 | 538 | ||
536 | static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, | 539 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
540 | struct fib6_table *table, | ||
537 | struct flowi *fl, int flags) | 541 | struct flowi *fl, int flags) |
538 | { | 542 | { |
539 | struct fib6_node *fn; | 543 | struct fib6_node *fn; |
@@ -543,8 +547,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); | 547 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
544 | restart: | 548 | restart: |
545 | rt = fn->leaf; | 549 | rt = fn->leaf; |
546 | rt = rt6_device_match(rt, fl->oif, flags); | 550 | rt = rt6_device_match(net, rt, fl->oif, flags); |
547 | BACKTRACK(&fl->fl6_src); | 551 | BACKTRACK(net, &fl->fl6_src); |
548 | out: | 552 | out: |
549 | dst_use(&rt->u.dst, jiffies); | 553 | dst_use(&rt->u.dst, jiffies); |
550 | read_unlock_bh(&table->tb6_lock); | 554 | read_unlock_bh(&table->tb6_lock); |
@@ -552,8 +556,8 @@ out: | |||
552 | 556 | ||
553 | } | 557 | } |
554 | 558 | ||
555 | struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | 559 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
556 | int oif, int strict) | 560 | const struct in6_addr *saddr, int oif, int strict) |
557 | { | 561 | { |
558 | struct flowi fl = { | 562 | struct flowi fl = { |
559 | .oif = oif, | 563 | .oif = oif, |
@@ -571,7 +575,7 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | |||
571 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 575 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
572 | } | 576 | } |
573 | 577 | ||
574 | dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); | 578 | dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup); |
575 | if (dst->error == 0) | 579 | if (dst->error == 0) |
576 | return (struct rt6_info *) dst; | 580 | return (struct rt6_info *) dst; |
577 | 581 | ||
@@ -604,7 +608,7 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) | |||
604 | int ip6_ins_rt(struct rt6_info *rt) | 608 | int ip6_ins_rt(struct rt6_info *rt) |
605 | { | 609 | { |
606 | struct nl_info info = { | 610 | struct nl_info info = { |
607 | .nl_net = &init_net, | 611 | .nl_net = dev_net(rt->rt6i_dev), |
608 | }; | 612 | }; |
609 | return __ip6_ins_rt(rt, &info); | 613 | return __ip6_ins_rt(rt, &info); |
610 | } | 614 | } |
@@ -660,8 +664,8 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
660 | return rt; | 664 | return rt; |
661 | } | 665 | } |
662 | 666 | ||
663 | static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif, | 667 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, |
664 | struct flowi *fl, int flags) | 668 | struct flowi *fl, int flags) |
665 | { | 669 | { |
666 | struct fib6_node *fn; | 670 | struct fib6_node *fn; |
667 | struct rt6_info *rt, *nrt; | 671 | struct rt6_info *rt, *nrt; |
@@ -680,8 +684,9 @@ restart_2: | |||
680 | 684 | ||
681 | restart: | 685 | restart: |
682 | rt = rt6_select(fn, oif, strict | reachable); | 686 | rt = rt6_select(fn, oif, strict | reachable); |
683 | BACKTRACK(&fl->fl6_src); | 687 | |
684 | if (rt == &ip6_null_entry || | 688 | BACKTRACK(net, &fl->fl6_src); |
689 | if (rt == net->ipv6.ip6_null_entry || | ||
685 | rt->rt6i_flags & RTF_CACHE) | 690 | rt->rt6i_flags & RTF_CACHE) |
686 | goto out; | 691 | goto out; |
687 | 692 | ||
@@ -699,7 +704,7 @@ restart: | |||
699 | } | 704 | } |
700 | 705 | ||
701 | dst_release(&rt->u.dst); | 706 | dst_release(&rt->u.dst); |
702 | rt = nrt ? : &ip6_null_entry; | 707 | rt = nrt ? : net->ipv6.ip6_null_entry; |
703 | 708 | ||
704 | dst_hold(&rt->u.dst); | 709 | dst_hold(&rt->u.dst); |
705 | if (nrt) { | 710 | if (nrt) { |
@@ -732,15 +737,16 @@ out2: | |||
732 | return rt; | 737 | return rt; |
733 | } | 738 | } |
734 | 739 | ||
735 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | 740 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, |
736 | struct flowi *fl, int flags) | 741 | struct flowi *fl, int flags) |
737 | { | 742 | { |
738 | return ip6_pol_route(table, fl->iif, fl, flags); | 743 | return ip6_pol_route(net, table, fl->iif, fl, flags); |
739 | } | 744 | } |
740 | 745 | ||
741 | void ip6_route_input(struct sk_buff *skb) | 746 | void ip6_route_input(struct sk_buff *skb) |
742 | { | 747 | { |
743 | struct ipv6hdr *iph = ipv6_hdr(skb); | 748 | struct ipv6hdr *iph = ipv6_hdr(skb); |
749 | struct net *net = dev_net(skb->dev); | ||
744 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 750 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
745 | struct flowi fl = { | 751 | struct flowi fl = { |
746 | .iif = skb->dev->ifindex, | 752 | .iif = skb->dev->ifindex, |
@@ -758,16 +764,17 @@ void ip6_route_input(struct sk_buff *skb) | |||
758 | if (rt6_need_strict(&iph->daddr)) | 764 | if (rt6_need_strict(&iph->daddr)) |
759 | flags |= RT6_LOOKUP_F_IFACE; | 765 | flags |= RT6_LOOKUP_F_IFACE; |
760 | 766 | ||
761 | skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); | 767 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); |
762 | } | 768 | } |
763 | 769 | ||
764 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | 770 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, |
765 | struct flowi *fl, int flags) | 771 | struct flowi *fl, int flags) |
766 | { | 772 | { |
767 | return ip6_pol_route(table, fl->oif, fl, flags); | 773 | return ip6_pol_route(net, table, fl->oif, fl, flags); |
768 | } | 774 | } |
769 | 775 | ||
770 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | 776 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, |
777 | struct flowi *fl) | ||
771 | { | 778 | { |
772 | int flags = 0; | 779 | int flags = 0; |
773 | 780 | ||
@@ -776,8 +783,17 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | |||
776 | 783 | ||
777 | if (!ipv6_addr_any(&fl->fl6_src)) | 784 | if (!ipv6_addr_any(&fl->fl6_src)) |
778 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 785 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
786 | else if (sk) { | ||
787 | unsigned int prefs = inet6_sk(sk)->srcprefs; | ||
788 | if (prefs & IPV6_PREFER_SRC_TMP) | ||
789 | flags |= RT6_LOOKUP_F_SRCPREF_TMP; | ||
790 | if (prefs & IPV6_PREFER_SRC_PUBLIC) | ||
791 | flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; | ||
792 | if (prefs & IPV6_PREFER_SRC_COA) | ||
793 | flags |= RT6_LOOKUP_F_SRCPREF_COA; | ||
794 | } | ||
779 | 795 | ||
780 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); | 796 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); |
781 | } | 797 | } |
782 | 798 | ||
783 | EXPORT_SYMBOL(ip6_route_output); | 799 | EXPORT_SYMBOL(ip6_route_output); |
@@ -886,12 +902,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
886 | 902 | ||
887 | static int ipv6_get_mtu(struct net_device *dev); | 903 | static int ipv6_get_mtu(struct net_device *dev); |
888 | 904 | ||
889 | static inline unsigned int ipv6_advmss(unsigned int mtu) | 905 | static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu) |
890 | { | 906 | { |
891 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); | 907 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); |
892 | 908 | ||
893 | if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss) | 909 | if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) |
894 | mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss; | 910 | mtu = net->ipv6.sysctl.ip6_rt_min_advmss; |
895 | 911 | ||
896 | /* | 912 | /* |
897 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and | 913 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and |
@@ -904,21 +920,21 @@ static inline unsigned int ipv6_advmss(unsigned int mtu) | |||
904 | return mtu; | 920 | return mtu; |
905 | } | 921 | } |
906 | 922 | ||
907 | static struct dst_entry *ndisc_dst_gc_list; | 923 | static struct dst_entry *icmp6_dst_gc_list; |
908 | static DEFINE_SPINLOCK(ndisc_lock); | 924 | static DEFINE_SPINLOCK(icmp6_dst_lock); |
909 | 925 | ||
910 | struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | 926 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
911 | struct neighbour *neigh, | 927 | struct neighbour *neigh, |
912 | struct in6_addr *addr, | 928 | const struct in6_addr *addr) |
913 | int (*output)(struct sk_buff *)) | ||
914 | { | 929 | { |
915 | struct rt6_info *rt; | 930 | struct rt6_info *rt; |
916 | struct inet6_dev *idev = in6_dev_get(dev); | 931 | struct inet6_dev *idev = in6_dev_get(dev); |
932 | struct net *net = dev_net(dev); | ||
917 | 933 | ||
918 | if (unlikely(idev == NULL)) | 934 | if (unlikely(idev == NULL)) |
919 | return NULL; | 935 | return NULL; |
920 | 936 | ||
921 | rt = ip6_dst_alloc(); | 937 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
922 | if (unlikely(rt == NULL)) { | 938 | if (unlikely(rt == NULL)) { |
923 | in6_dev_put(idev); | 939 | in6_dev_put(idev); |
924 | goto out; | 940 | goto out; |
@@ -936,8 +952,8 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
936 | atomic_set(&rt->u.dst.__refcnt, 1); | 952 | atomic_set(&rt->u.dst.__refcnt, 1); |
937 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; | 953 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; |
938 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 954 | 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)); | 955 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
940 | rt->u.dst.output = output; | 956 | rt->u.dst.output = ip6_output; |
941 | 957 | ||
942 | #if 0 /* there's no chance to use these for ndisc */ | 958 | #if 0 /* there's no chance to use these for ndisc */ |
943 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | 959 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST |
@@ -947,18 +963,18 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
947 | rt->rt6i_dst.plen = 128; | 963 | rt->rt6i_dst.plen = 128; |
948 | #endif | 964 | #endif |
949 | 965 | ||
950 | spin_lock_bh(&ndisc_lock); | 966 | spin_lock_bh(&icmp6_dst_lock); |
951 | rt->u.dst.next = ndisc_dst_gc_list; | 967 | rt->u.dst.next = icmp6_dst_gc_list; |
952 | ndisc_dst_gc_list = &rt->u.dst; | 968 | icmp6_dst_gc_list = &rt->u.dst; |
953 | spin_unlock_bh(&ndisc_lock); | 969 | spin_unlock_bh(&icmp6_dst_lock); |
954 | 970 | ||
955 | fib6_force_start_gc(); | 971 | fib6_force_start_gc(net); |
956 | 972 | ||
957 | out: | 973 | out: |
958 | return &rt->u.dst; | 974 | return &rt->u.dst; |
959 | } | 975 | } |
960 | 976 | ||
961 | int ndisc_dst_gc(int *more) | 977 | int icmp6_dst_gc(int *more) |
962 | { | 978 | { |
963 | struct dst_entry *dst, *next, **pprev; | 979 | struct dst_entry *dst, *next, **pprev; |
964 | int freed; | 980 | int freed; |
@@ -966,8 +982,8 @@ int ndisc_dst_gc(int *more) | |||
966 | next = NULL; | 982 | next = NULL; |
967 | freed = 0; | 983 | freed = 0; |
968 | 984 | ||
969 | spin_lock_bh(&ndisc_lock); | 985 | spin_lock_bh(&icmp6_dst_lock); |
970 | pprev = &ndisc_dst_gc_list; | 986 | pprev = &icmp6_dst_gc_list; |
971 | 987 | ||
972 | while ((dst = *pprev) != NULL) { | 988 | while ((dst = *pprev) != NULL) { |
973 | if (!atomic_read(&dst->__refcnt)) { | 989 | if (!atomic_read(&dst->__refcnt)) { |
@@ -980,30 +996,33 @@ int ndisc_dst_gc(int *more) | |||
980 | } | 996 | } |
981 | } | 997 | } |
982 | 998 | ||
983 | spin_unlock_bh(&ndisc_lock); | 999 | spin_unlock_bh(&icmp6_dst_lock); |
984 | 1000 | ||
985 | return freed; | 1001 | return freed; |
986 | } | 1002 | } |
987 | 1003 | ||
988 | static int ip6_dst_gc(struct dst_ops *ops) | 1004 | static int ip6_dst_gc(struct dst_ops *ops) |
989 | { | 1005 | { |
990 | static unsigned expire = 30*HZ; | ||
991 | static unsigned long last_gc; | ||
992 | unsigned long now = jiffies; | 1006 | unsigned long now = jiffies; |
993 | 1007 | struct net *net = ops->dst_net; | |
994 | if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) && | 1008 | 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) | 1009 | int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; |
1010 | int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
1011 | int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
1012 | unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; | ||
1013 | |||
1014 | if (time_after(rt_last_gc + rt_min_interval, now) && | ||
1015 | atomic_read(&ops->entries) <= rt_max_size) | ||
996 | goto out; | 1016 | goto out; |
997 | 1017 | ||
998 | expire++; | 1018 | net->ipv6.ip6_rt_gc_expire++; |
999 | fib6_run_gc(expire); | 1019 | fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net); |
1000 | last_gc = now; | 1020 | net->ipv6.ip6_rt_last_gc = now; |
1001 | if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh) | 1021 | if (atomic_read(&ops->entries) < ops->gc_thresh) |
1002 | expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1; | 1022 | net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; |
1003 | |||
1004 | out: | 1023 | out: |
1005 | expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity; | 1024 | 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); | 1025 | return (atomic_read(&ops->entries) > rt_max_size); |
1007 | } | 1026 | } |
1008 | 1027 | ||
1009 | /* Clean host part of a prefix. Not necessary in radix tree, | 1028 | /* Clean host part of a prefix. Not necessary in radix tree, |
@@ -1025,15 +1044,17 @@ static int ipv6_get_mtu(struct net_device *dev) | |||
1025 | return mtu; | 1044 | return mtu; |
1026 | } | 1045 | } |
1027 | 1046 | ||
1028 | int ipv6_get_hoplimit(struct net_device *dev) | 1047 | int ip6_dst_hoplimit(struct dst_entry *dst) |
1029 | { | 1048 | { |
1030 | int hoplimit = ipv6_devconf.hop_limit; | 1049 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); |
1031 | struct inet6_dev *idev; | 1050 | if (hoplimit < 0) { |
1032 | 1051 | struct net_device *dev = dst->dev; | |
1033 | idev = in6_dev_get(dev); | 1052 | struct inet6_dev *idev = in6_dev_get(dev); |
1034 | if (idev) { | 1053 | if (idev) { |
1035 | hoplimit = idev->cnf.hop_limit; | 1054 | hoplimit = idev->cnf.hop_limit; |
1036 | in6_dev_put(idev); | 1055 | in6_dev_put(idev); |
1056 | } else | ||
1057 | hoplimit = ipv6_devconf.hop_limit; | ||
1037 | } | 1058 | } |
1038 | return hoplimit; | 1059 | return hoplimit; |
1039 | } | 1060 | } |
@@ -1045,6 +1066,7 @@ int ipv6_get_hoplimit(struct net_device *dev) | |||
1045 | int ip6_route_add(struct fib6_config *cfg) | 1066 | int ip6_route_add(struct fib6_config *cfg) |
1046 | { | 1067 | { |
1047 | int err; | 1068 | int err; |
1069 | struct net *net = cfg->fc_nlinfo.nl_net; | ||
1048 | struct rt6_info *rt = NULL; | 1070 | struct rt6_info *rt = NULL; |
1049 | struct net_device *dev = NULL; | 1071 | struct net_device *dev = NULL; |
1050 | struct inet6_dev *idev = NULL; | 1072 | struct inet6_dev *idev = NULL; |
@@ -1059,7 +1081,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1059 | #endif | 1081 | #endif |
1060 | if (cfg->fc_ifindex) { | 1082 | if (cfg->fc_ifindex) { |
1061 | err = -ENODEV; | 1083 | err = -ENODEV; |
1062 | dev = dev_get_by_index(&init_net, cfg->fc_ifindex); | 1084 | dev = dev_get_by_index(net, cfg->fc_ifindex); |
1063 | if (!dev) | 1085 | if (!dev) |
1064 | goto out; | 1086 | goto out; |
1065 | idev = in6_dev_get(dev); | 1087 | idev = in6_dev_get(dev); |
@@ -1070,13 +1092,13 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1070 | if (cfg->fc_metric == 0) | 1092 | if (cfg->fc_metric == 0) |
1071 | cfg->fc_metric = IP6_RT_PRIO_USER; | 1093 | cfg->fc_metric = IP6_RT_PRIO_USER; |
1072 | 1094 | ||
1073 | table = fib6_new_table(cfg->fc_table); | 1095 | table = fib6_new_table(net, cfg->fc_table); |
1074 | if (table == NULL) { | 1096 | if (table == NULL) { |
1075 | err = -ENOBUFS; | 1097 | err = -ENOBUFS; |
1076 | goto out; | 1098 | goto out; |
1077 | } | 1099 | } |
1078 | 1100 | ||
1079 | rt = ip6_dst_alloc(); | 1101 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
1080 | 1102 | ||
1081 | if (rt == NULL) { | 1103 | if (rt == NULL) { |
1082 | err = -ENOMEM; | 1104 | err = -ENOMEM; |
@@ -1117,12 +1139,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1117 | if ((cfg->fc_flags & RTF_REJECT) || | 1139 | if ((cfg->fc_flags & RTF_REJECT) || |
1118 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { | 1140 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { |
1119 | /* hold loopback dev/idev if we haven't done so. */ | 1141 | /* hold loopback dev/idev if we haven't done so. */ |
1120 | if (dev != init_net.loopback_dev) { | 1142 | if (dev != net->loopback_dev) { |
1121 | if (dev) { | 1143 | if (dev) { |
1122 | dev_put(dev); | 1144 | dev_put(dev); |
1123 | in6_dev_put(idev); | 1145 | in6_dev_put(idev); |
1124 | } | 1146 | } |
1125 | dev = init_net.loopback_dev; | 1147 | dev = net->loopback_dev; |
1126 | dev_hold(dev); | 1148 | dev_hold(dev); |
1127 | idev = in6_dev_get(dev); | 1149 | idev = in6_dev_get(dev); |
1128 | if (!idev) { | 1150 | if (!idev) { |
@@ -1159,7 +1181,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1159 | if (!(gwa_type&IPV6_ADDR_UNICAST)) | 1181 | if (!(gwa_type&IPV6_ADDR_UNICAST)) |
1160 | goto out; | 1182 | goto out; |
1161 | 1183 | ||
1162 | grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1); | 1184 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); |
1163 | 1185 | ||
1164 | err = -EHOSTUNREACH; | 1186 | err = -EHOSTUNREACH; |
1165 | if (grt == NULL) | 1187 | if (grt == NULL) |
@@ -1226,10 +1248,13 @@ install_route: | |||
1226 | if (!rt->u.dst.metrics[RTAX_MTU-1]) | 1248 | if (!rt->u.dst.metrics[RTAX_MTU-1]) |
1227 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1249 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); |
1228 | if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) | 1250 | if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) |
1229 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); | 1251 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
1230 | rt->u.dst.dev = dev; | 1252 | rt->u.dst.dev = dev; |
1231 | rt->rt6i_idev = idev; | 1253 | rt->rt6i_idev = idev; |
1232 | rt->rt6i_table = table; | 1254 | rt->rt6i_table = table; |
1255 | |||
1256 | cfg->fc_nlinfo.nl_net = dev_net(dev); | ||
1257 | |||
1233 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); | 1258 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); |
1234 | 1259 | ||
1235 | out: | 1260 | out: |
@@ -1246,8 +1271,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1246 | { | 1271 | { |
1247 | int err; | 1272 | int err; |
1248 | struct fib6_table *table; | 1273 | struct fib6_table *table; |
1274 | struct net *net = dev_net(rt->rt6i_dev); | ||
1249 | 1275 | ||
1250 | if (rt == &ip6_null_entry) | 1276 | if (rt == net->ipv6.ip6_null_entry) |
1251 | return -ENOENT; | 1277 | return -ENOENT; |
1252 | 1278 | ||
1253 | table = rt->rt6i_table; | 1279 | table = rt->rt6i_table; |
@@ -1264,7 +1290,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1264 | int ip6_del_rt(struct rt6_info *rt) | 1290 | int ip6_del_rt(struct rt6_info *rt) |
1265 | { | 1291 | { |
1266 | struct nl_info info = { | 1292 | struct nl_info info = { |
1267 | .nl_net = &init_net, | 1293 | .nl_net = dev_net(rt->rt6i_dev), |
1268 | }; | 1294 | }; |
1269 | return __ip6_del_rt(rt, &info); | 1295 | return __ip6_del_rt(rt, &info); |
1270 | } | 1296 | } |
@@ -1276,7 +1302,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1276 | struct rt6_info *rt; | 1302 | struct rt6_info *rt; |
1277 | int err = -ESRCH; | 1303 | int err = -ESRCH; |
1278 | 1304 | ||
1279 | table = fib6_get_table(cfg->fc_table); | 1305 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); |
1280 | if (table == NULL) | 1306 | if (table == NULL) |
1281 | return err; | 1307 | return err; |
1282 | 1308 | ||
@@ -1316,7 +1342,8 @@ struct ip6rd_flowi { | |||
1316 | struct in6_addr gateway; | 1342 | struct in6_addr gateway; |
1317 | }; | 1343 | }; |
1318 | 1344 | ||
1319 | static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, | 1345 | static struct rt6_info *__ip6_route_redirect(struct net *net, |
1346 | struct fib6_table *table, | ||
1320 | struct flowi *fl, | 1347 | struct flowi *fl, |
1321 | int flags) | 1348 | int flags) |
1322 | { | 1349 | { |
@@ -1359,8 +1386,8 @@ restart: | |||
1359 | } | 1386 | } |
1360 | 1387 | ||
1361 | if (!rt) | 1388 | if (!rt) |
1362 | rt = &ip6_null_entry; | 1389 | rt = net->ipv6.ip6_null_entry; |
1363 | BACKTRACK(&fl->fl6_src); | 1390 | BACKTRACK(net, &fl->fl6_src); |
1364 | out: | 1391 | out: |
1365 | dst_hold(&rt->u.dst); | 1392 | dst_hold(&rt->u.dst); |
1366 | 1393 | ||
@@ -1375,6 +1402,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1375 | struct net_device *dev) | 1402 | struct net_device *dev) |
1376 | { | 1403 | { |
1377 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 1404 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
1405 | struct net *net = dev_net(dev); | ||
1378 | struct ip6rd_flowi rdfl = { | 1406 | struct ip6rd_flowi rdfl = { |
1379 | .fl = { | 1407 | .fl = { |
1380 | .oif = dev->ifindex, | 1408 | .oif = dev->ifindex, |
@@ -1391,7 +1419,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1391 | if (rt6_need_strict(dest)) | 1419 | if (rt6_need_strict(dest)) |
1392 | flags |= RT6_LOOKUP_F_IFACE; | 1420 | flags |= RT6_LOOKUP_F_IFACE; |
1393 | 1421 | ||
1394 | return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); | 1422 | return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl, |
1423 | flags, __ip6_route_redirect); | ||
1395 | } | 1424 | } |
1396 | 1425 | ||
1397 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | 1426 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, |
@@ -1400,10 +1429,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1400 | { | 1429 | { |
1401 | struct rt6_info *rt, *nrt = NULL; | 1430 | struct rt6_info *rt, *nrt = NULL; |
1402 | struct netevent_redirect netevent; | 1431 | struct netevent_redirect netevent; |
1432 | struct net *net = dev_net(neigh->dev); | ||
1403 | 1433 | ||
1404 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); | 1434 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); |
1405 | 1435 | ||
1406 | if (rt == &ip6_null_entry) { | 1436 | if (rt == net->ipv6.ip6_null_entry) { |
1407 | if (net_ratelimit()) | 1437 | if (net_ratelimit()) |
1408 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " | 1438 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " |
1409 | "for redirect target\n"); | 1439 | "for redirect target\n"); |
@@ -1448,7 +1478,8 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1448 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1478 | nrt->rt6i_nexthop = neigh_clone(neigh); |
1449 | /* Reset pmtu, it may be better */ | 1479 | /* Reset pmtu, it may be better */ |
1450 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1480 | 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)); | 1481 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), |
1482 | dst_mtu(&nrt->u.dst)); | ||
1452 | 1483 | ||
1453 | if (ip6_ins_rt(nrt)) | 1484 | if (ip6_ins_rt(nrt)) |
1454 | goto out; | 1485 | goto out; |
@@ -1476,9 +1507,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1476 | struct net_device *dev, u32 pmtu) | 1507 | struct net_device *dev, u32 pmtu) |
1477 | { | 1508 | { |
1478 | struct rt6_info *rt, *nrt; | 1509 | struct rt6_info *rt, *nrt; |
1510 | struct net *net = dev_net(dev); | ||
1479 | int allfrag = 0; | 1511 | int allfrag = 0; |
1480 | 1512 | ||
1481 | rt = rt6_lookup(daddr, saddr, dev->ifindex, 0); | 1513 | rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0); |
1482 | if (rt == NULL) | 1514 | if (rt == NULL) |
1483 | return; | 1515 | return; |
1484 | 1516 | ||
@@ -1511,7 +1543,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1511 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1543 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; |
1512 | if (allfrag) | 1544 | if (allfrag) |
1513 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1545 | 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); | 1546 | dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1515 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1547 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
1516 | goto out; | 1548 | goto out; |
1517 | } | 1549 | } |
@@ -1537,7 +1569,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 | 1569 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
1538 | * and detecting PMTU increase will be automatically happened. | 1570 | * and detecting PMTU increase will be automatically happened. |
1539 | */ | 1571 | */ |
1540 | dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires); | 1572 | dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1541 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1573 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; |
1542 | 1574 | ||
1543 | ip6_ins_rt(nrt); | 1575 | ip6_ins_rt(nrt); |
@@ -1552,7 +1584,8 @@ out: | |||
1552 | 1584 | ||
1553 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1585 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) |
1554 | { | 1586 | { |
1555 | struct rt6_info *rt = ip6_dst_alloc(); | 1587 | struct net *net = dev_net(ort->rt6i_dev); |
1588 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1556 | 1589 | ||
1557 | if (rt) { | 1590 | if (rt) { |
1558 | rt->u.dst.input = ort->u.dst.input; | 1591 | rt->u.dst.input = ort->u.dst.input; |
@@ -1583,14 +1616,15 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1583 | } | 1616 | } |
1584 | 1617 | ||
1585 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1618 | #ifdef CONFIG_IPV6_ROUTE_INFO |
1586 | static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, | 1619 | static struct rt6_info *rt6_get_route_info(struct net *net, |
1620 | struct in6_addr *prefix, int prefixlen, | ||
1587 | struct in6_addr *gwaddr, int ifindex) | 1621 | struct in6_addr *gwaddr, int ifindex) |
1588 | { | 1622 | { |
1589 | struct fib6_node *fn; | 1623 | struct fib6_node *fn; |
1590 | struct rt6_info *rt = NULL; | 1624 | struct rt6_info *rt = NULL; |
1591 | struct fib6_table *table; | 1625 | struct fib6_table *table; |
1592 | 1626 | ||
1593 | table = fib6_get_table(RT6_TABLE_INFO); | 1627 | table = fib6_get_table(net, RT6_TABLE_INFO); |
1594 | if (table == NULL) | 1628 | if (table == NULL) |
1595 | return NULL; | 1629 | return NULL; |
1596 | 1630 | ||
@@ -1614,7 +1648,8 @@ out: | |||
1614 | return rt; | 1648 | return rt; |
1615 | } | 1649 | } |
1616 | 1650 | ||
1617 | static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, | 1651 | static struct rt6_info *rt6_add_route_info(struct net *net, |
1652 | struct in6_addr *prefix, int prefixlen, | ||
1618 | struct in6_addr *gwaddr, int ifindex, | 1653 | struct in6_addr *gwaddr, int ifindex, |
1619 | unsigned pref) | 1654 | unsigned pref) |
1620 | { | 1655 | { |
@@ -1625,6 +1660,9 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle | |||
1625 | .fc_dst_len = prefixlen, | 1660 | .fc_dst_len = prefixlen, |
1626 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | | 1661 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | |
1627 | RTF_UP | RTF_PREF(pref), | 1662 | RTF_UP | RTF_PREF(pref), |
1663 | .fc_nlinfo.pid = 0, | ||
1664 | .fc_nlinfo.nlh = NULL, | ||
1665 | .fc_nlinfo.nl_net = net, | ||
1628 | }; | 1666 | }; |
1629 | 1667 | ||
1630 | ipv6_addr_copy(&cfg.fc_dst, prefix); | 1668 | ipv6_addr_copy(&cfg.fc_dst, prefix); |
@@ -1636,7 +1674,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle | |||
1636 | 1674 | ||
1637 | ip6_route_add(&cfg); | 1675 | ip6_route_add(&cfg); |
1638 | 1676 | ||
1639 | return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); | 1677 | return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex); |
1640 | } | 1678 | } |
1641 | #endif | 1679 | #endif |
1642 | 1680 | ||
@@ -1645,7 +1683,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1645 | struct rt6_info *rt; | 1683 | struct rt6_info *rt; |
1646 | struct fib6_table *table; | 1684 | struct fib6_table *table; |
1647 | 1685 | ||
1648 | table = fib6_get_table(RT6_TABLE_DFLT); | 1686 | table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); |
1649 | if (table == NULL) | 1687 | if (table == NULL) |
1650 | return NULL; | 1688 | return NULL; |
1651 | 1689 | ||
@@ -1662,8 +1700,6 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1662 | return rt; | 1700 | return rt; |
1663 | } | 1701 | } |
1664 | 1702 | ||
1665 | EXPORT_SYMBOL(rt6_get_dflt_router); | ||
1666 | |||
1667 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | 1703 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, |
1668 | struct net_device *dev, | 1704 | struct net_device *dev, |
1669 | unsigned int pref) | 1705 | unsigned int pref) |
@@ -1674,6 +1710,9 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1674 | .fc_ifindex = dev->ifindex, | 1710 | .fc_ifindex = dev->ifindex, |
1675 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | | 1711 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | |
1676 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), | 1712 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), |
1713 | .fc_nlinfo.pid = 0, | ||
1714 | .fc_nlinfo.nlh = NULL, | ||
1715 | .fc_nlinfo.nl_net = dev_net(dev), | ||
1677 | }; | 1716 | }; |
1678 | 1717 | ||
1679 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1718 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); |
@@ -1683,13 +1722,13 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1683 | return rt6_get_dflt_router(gwaddr, dev); | 1722 | return rt6_get_dflt_router(gwaddr, dev); |
1684 | } | 1723 | } |
1685 | 1724 | ||
1686 | void rt6_purge_dflt_routers(void) | 1725 | void rt6_purge_dflt_routers(struct net *net) |
1687 | { | 1726 | { |
1688 | struct rt6_info *rt; | 1727 | struct rt6_info *rt; |
1689 | struct fib6_table *table; | 1728 | struct fib6_table *table; |
1690 | 1729 | ||
1691 | /* NOTE: Keep consistent with rt6_get_dflt_router */ | 1730 | /* NOTE: Keep consistent with rt6_get_dflt_router */ |
1692 | table = fib6_get_table(RT6_TABLE_DFLT); | 1731 | table = fib6_get_table(net, RT6_TABLE_DFLT); |
1693 | if (table == NULL) | 1732 | if (table == NULL) |
1694 | return; | 1733 | return; |
1695 | 1734 | ||
@@ -1706,7 +1745,8 @@ restart: | |||
1706 | read_unlock_bh(&table->tb6_lock); | 1745 | read_unlock_bh(&table->tb6_lock); |
1707 | } | 1746 | } |
1708 | 1747 | ||
1709 | static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, | 1748 | static void rtmsg_to_fib6_config(struct net *net, |
1749 | struct in6_rtmsg *rtmsg, | ||
1710 | struct fib6_config *cfg) | 1750 | struct fib6_config *cfg) |
1711 | { | 1751 | { |
1712 | memset(cfg, 0, sizeof(*cfg)); | 1752 | memset(cfg, 0, sizeof(*cfg)); |
@@ -1719,14 +1759,14 @@ static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, | |||
1719 | cfg->fc_src_len = rtmsg->rtmsg_src_len; | 1759 | cfg->fc_src_len = rtmsg->rtmsg_src_len; |
1720 | cfg->fc_flags = rtmsg->rtmsg_flags; | 1760 | cfg->fc_flags = rtmsg->rtmsg_flags; |
1721 | 1761 | ||
1722 | cfg->fc_nlinfo.nl_net = &init_net; | 1762 | cfg->fc_nlinfo.nl_net = net; |
1723 | 1763 | ||
1724 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); | 1764 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); |
1725 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); | 1765 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); |
1726 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); | 1766 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); |
1727 | } | 1767 | } |
1728 | 1768 | ||
1729 | int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | 1769 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
1730 | { | 1770 | { |
1731 | struct fib6_config cfg; | 1771 | struct fib6_config cfg; |
1732 | struct in6_rtmsg rtmsg; | 1772 | struct in6_rtmsg rtmsg; |
@@ -1742,7 +1782,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1742 | if (err) | 1782 | if (err) |
1743 | return -EFAULT; | 1783 | return -EFAULT; |
1744 | 1784 | ||
1745 | rtmsg_to_fib6_config(&rtmsg, &cfg); | 1785 | rtmsg_to_fib6_config(net, &rtmsg, &cfg); |
1746 | 1786 | ||
1747 | rtnl_lock(); | 1787 | rtnl_lock(); |
1748 | switch (cmd) { | 1788 | switch (cmd) { |
@@ -1821,21 +1861,22 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1821 | const struct in6_addr *addr, | 1861 | const struct in6_addr *addr, |
1822 | int anycast) | 1862 | int anycast) |
1823 | { | 1863 | { |
1824 | struct rt6_info *rt = ip6_dst_alloc(); | 1864 | struct net *net = dev_net(idev->dev); |
1865 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1825 | 1866 | ||
1826 | if (rt == NULL) | 1867 | if (rt == NULL) |
1827 | return ERR_PTR(-ENOMEM); | 1868 | return ERR_PTR(-ENOMEM); |
1828 | 1869 | ||
1829 | dev_hold(init_net.loopback_dev); | 1870 | dev_hold(net->loopback_dev); |
1830 | in6_dev_hold(idev); | 1871 | in6_dev_hold(idev); |
1831 | 1872 | ||
1832 | rt->u.dst.flags = DST_HOST; | 1873 | rt->u.dst.flags = DST_HOST; |
1833 | rt->u.dst.input = ip6_input; | 1874 | rt->u.dst.input = ip6_input; |
1834 | rt->u.dst.output = ip6_output; | 1875 | rt->u.dst.output = ip6_output; |
1835 | rt->rt6i_dev = init_net.loopback_dev; | 1876 | rt->rt6i_dev = net->loopback_dev; |
1836 | rt->rt6i_idev = idev; | 1877 | rt->rt6i_idev = idev; |
1837 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1878 | 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)); | 1879 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); |
1839 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1880 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; |
1840 | rt->u.dst.obsolete = -1; | 1881 | rt->u.dst.obsolete = -1; |
1841 | 1882 | ||
@@ -1852,26 +1893,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1852 | 1893 | ||
1853 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1894 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
1854 | rt->rt6i_dst.plen = 128; | 1895 | rt->rt6i_dst.plen = 128; |
1855 | rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL); | 1896 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
1856 | 1897 | ||
1857 | atomic_set(&rt->u.dst.__refcnt, 1); | 1898 | atomic_set(&rt->u.dst.__refcnt, 1); |
1858 | 1899 | ||
1859 | return rt; | 1900 | return rt; |
1860 | } | 1901 | } |
1861 | 1902 | ||
1903 | struct arg_dev_net { | ||
1904 | struct net_device *dev; | ||
1905 | struct net *net; | ||
1906 | }; | ||
1907 | |||
1862 | static int fib6_ifdown(struct rt6_info *rt, void *arg) | 1908 | static int fib6_ifdown(struct rt6_info *rt, void *arg) |
1863 | { | 1909 | { |
1864 | if (((void*)rt->rt6i_dev == arg || arg == NULL) && | 1910 | struct net_device *dev = ((struct arg_dev_net *)arg)->dev; |
1865 | rt != &ip6_null_entry) { | 1911 | struct net *net = ((struct arg_dev_net *)arg)->net; |
1912 | |||
1913 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | ||
1914 | rt != net->ipv6.ip6_null_entry) { | ||
1866 | RT6_TRACE("deleted by ifdown %p\n", rt); | 1915 | RT6_TRACE("deleted by ifdown %p\n", rt); |
1867 | return -1; | 1916 | return -1; |
1868 | } | 1917 | } |
1869 | return 0; | 1918 | return 0; |
1870 | } | 1919 | } |
1871 | 1920 | ||
1872 | void rt6_ifdown(struct net_device *dev) | 1921 | void rt6_ifdown(struct net *net, struct net_device *dev) |
1873 | { | 1922 | { |
1874 | fib6_clean_all(fib6_ifdown, 0, dev); | 1923 | struct arg_dev_net adn = { |
1924 | .dev = dev, | ||
1925 | .net = net, | ||
1926 | }; | ||
1927 | |||
1928 | fib6_clean_all(net, fib6_ifdown, 0, &adn); | ||
1875 | } | 1929 | } |
1876 | 1930 | ||
1877 | struct rt6_mtu_change_arg | 1931 | struct rt6_mtu_change_arg |
@@ -1884,6 +1938,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
1884 | { | 1938 | { |
1885 | struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; | 1939 | struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; |
1886 | struct inet6_dev *idev; | 1940 | struct inet6_dev *idev; |
1941 | struct net *net = dev_net(arg->dev); | ||
1887 | 1942 | ||
1888 | /* In IPv6 pmtu discovery is not optional, | 1943 | /* In IPv6 pmtu discovery is not optional, |
1889 | so that RTAX_MTU lock cannot disable it. | 1944 | so that RTAX_MTU lock cannot disable it. |
@@ -1915,7 +1970,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
1915 | (dst_mtu(&rt->u.dst) < arg->mtu && | 1970 | (dst_mtu(&rt->u.dst) < arg->mtu && |
1916 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { | 1971 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { |
1917 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; | 1972 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; |
1918 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu); | 1973 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); |
1919 | } | 1974 | } |
1920 | return 0; | 1975 | return 0; |
1921 | } | 1976 | } |
@@ -1927,7 +1982,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu) | |||
1927 | .mtu = mtu, | 1982 | .mtu = mtu, |
1928 | }; | 1983 | }; |
1929 | 1984 | ||
1930 | fib6_clean_all(rt6_mtu_change_route, 0, &arg); | 1985 | fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg); |
1931 | } | 1986 | } |
1932 | 1987 | ||
1933 | static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { | 1988 | static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { |
@@ -1964,7 +2019,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1964 | 2019 | ||
1965 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; | 2020 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; |
1966 | cfg->fc_nlinfo.nlh = nlh; | 2021 | cfg->fc_nlinfo.nlh = nlh; |
1967 | cfg->fc_nlinfo.nl_net = skb->sk->sk_net; | 2022 | cfg->fc_nlinfo.nl_net = sock_net(skb->sk); |
1968 | 2023 | ||
1969 | if (tb[RTA_GATEWAY]) { | 2024 | if (tb[RTA_GATEWAY]) { |
1970 | nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16); | 2025 | nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16); |
@@ -2010,13 +2065,9 @@ errout: | |||
2010 | 2065 | ||
2011 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2066 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2012 | { | 2067 | { |
2013 | struct net *net = skb->sk->sk_net; | ||
2014 | struct fib6_config cfg; | 2068 | struct fib6_config cfg; |
2015 | int err; | 2069 | int err; |
2016 | 2070 | ||
2017 | if (net != &init_net) | ||
2018 | return -EINVAL; | ||
2019 | |||
2020 | err = rtm_to_fib6_config(skb, nlh, &cfg); | 2071 | err = rtm_to_fib6_config(skb, nlh, &cfg); |
2021 | if (err < 0) | 2072 | if (err < 0) |
2022 | return err; | 2073 | return err; |
@@ -2026,13 +2077,9 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a | |||
2026 | 2077 | ||
2027 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2078 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2028 | { | 2079 | { |
2029 | struct net *net = skb->sk->sk_net; | ||
2030 | struct fib6_config cfg; | 2080 | struct fib6_config cfg; |
2031 | int err; | 2081 | int err; |
2032 | 2082 | ||
2033 | if (net != &init_net) | ||
2034 | return -EINVAL; | ||
2035 | |||
2036 | err = rtm_to_fib6_config(skb, nlh, &cfg); | 2083 | err = rtm_to_fib6_config(skb, nlh, &cfg); |
2037 | if (err < 0) | 2084 | if (err < 0) |
2038 | return err; | 2085 | return err; |
@@ -2058,7 +2105,7 @@ static inline size_t rt6_nlmsg_size(void) | |||
2058 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | 2105 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, |
2059 | struct in6_addr *dst, struct in6_addr *src, | 2106 | struct in6_addr *dst, struct in6_addr *src, |
2060 | int iif, int type, u32 pid, u32 seq, | 2107 | int iif, int type, u32 pid, u32 seq, |
2061 | int prefix, unsigned int flags) | 2108 | int prefix, int nowait, unsigned int flags) |
2062 | { | 2109 | { |
2063 | struct rtmsg *rtm; | 2110 | struct rtmsg *rtm; |
2064 | struct nlmsghdr *nlh; | 2111 | struct nlmsghdr *nlh; |
@@ -2118,11 +2165,27 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2118 | } else if (rtm->rtm_src_len) | 2165 | } else if (rtm->rtm_src_len) |
2119 | NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); | 2166 | NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); |
2120 | #endif | 2167 | #endif |
2121 | if (iif) | 2168 | if (iif) { |
2122 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2169 | #ifdef CONFIG_IPV6_MROUTE |
2123 | else if (dst) { | 2170 | if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { |
2171 | int err = ip6mr_get_route(skb, rtm, nowait); | ||
2172 | if (err <= 0) { | ||
2173 | if (!nowait) { | ||
2174 | if (err == 0) | ||
2175 | return 0; | ||
2176 | goto nla_put_failure; | ||
2177 | } else { | ||
2178 | if (err == -EMSGSIZE) | ||
2179 | goto nla_put_failure; | ||
2180 | } | ||
2181 | } | ||
2182 | } else | ||
2183 | #endif | ||
2184 | NLA_PUT_U32(skb, RTA_IIF, iif); | ||
2185 | } else if (dst) { | ||
2124 | struct in6_addr saddr_buf; | 2186 | struct in6_addr saddr_buf; |
2125 | if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) | 2187 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, |
2188 | dst, 0, &saddr_buf) == 0) | ||
2126 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2189 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2127 | } | 2190 | } |
2128 | 2191 | ||
@@ -2162,12 +2225,12 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2162 | 2225 | ||
2163 | return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, | 2226 | return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, |
2164 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, | 2227 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, |
2165 | prefix, NLM_F_MULTI); | 2228 | prefix, 0, NLM_F_MULTI); |
2166 | } | 2229 | } |
2167 | 2230 | ||
2168 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | 2231 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) |
2169 | { | 2232 | { |
2170 | struct net *net = in_skb->sk->sk_net; | 2233 | struct net *net = sock_net(in_skb->sk); |
2171 | struct nlattr *tb[RTA_MAX+1]; | 2234 | struct nlattr *tb[RTA_MAX+1]; |
2172 | struct rt6_info *rt; | 2235 | struct rt6_info *rt; |
2173 | struct sk_buff *skb; | 2236 | struct sk_buff *skb; |
@@ -2175,9 +2238,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2175 | struct flowi fl; | 2238 | struct flowi fl; |
2176 | int err, iif = 0; | 2239 | int err, iif = 0; |
2177 | 2240 | ||
2178 | if (net != &init_net) | ||
2179 | return -EINVAL; | ||
2180 | |||
2181 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); | 2241 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); |
2182 | if (err < 0) | 2242 | if (err < 0) |
2183 | goto errout; | 2243 | goto errout; |
@@ -2207,7 +2267,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2207 | 2267 | ||
2208 | if (iif) { | 2268 | if (iif) { |
2209 | struct net_device *dev; | 2269 | struct net_device *dev; |
2210 | dev = __dev_get_by_index(&init_net, iif); | 2270 | dev = __dev_get_by_index(net, iif); |
2211 | if (!dev) { | 2271 | if (!dev) { |
2212 | err = -ENODEV; | 2272 | err = -ENODEV; |
2213 | goto errout; | 2273 | goto errout; |
@@ -2226,18 +2286,18 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2226 | skb_reset_mac_header(skb); | 2286 | skb_reset_mac_header(skb); |
2227 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2287 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2228 | 2288 | ||
2229 | rt = (struct rt6_info*) ip6_route_output(NULL, &fl); | 2289 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); |
2230 | skb->dst = &rt->u.dst; | 2290 | skb->dst = &rt->u.dst; |
2231 | 2291 | ||
2232 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2292 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
2233 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2293 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
2234 | nlh->nlmsg_seq, 0, 0); | 2294 | nlh->nlmsg_seq, 0, 0, 0); |
2235 | if (err < 0) { | 2295 | if (err < 0) { |
2236 | kfree_skb(skb); | 2296 | kfree_skb(skb); |
2237 | goto errout; | 2297 | goto errout; |
2238 | } | 2298 | } |
2239 | 2299 | ||
2240 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 2300 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
2241 | errout: | 2301 | errout: |
2242 | return err; | 2302 | return err; |
2243 | } | 2303 | } |
@@ -2245,6 +2305,7 @@ errout: | |||
2245 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | 2305 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) |
2246 | { | 2306 | { |
2247 | struct sk_buff *skb; | 2307 | struct sk_buff *skb; |
2308 | struct net *net = info->nl_net; | ||
2248 | u32 seq; | 2309 | u32 seq; |
2249 | int err; | 2310 | int err; |
2250 | 2311 | ||
@@ -2256,18 +2317,38 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2256 | goto errout; | 2317 | goto errout; |
2257 | 2318 | ||
2258 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, | 2319 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, |
2259 | event, info->pid, seq, 0, 0); | 2320 | event, info->pid, seq, 0, 0, 0); |
2260 | if (err < 0) { | 2321 | if (err < 0) { |
2261 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ | 2322 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ |
2262 | WARN_ON(err == -EMSGSIZE); | 2323 | WARN_ON(err == -EMSGSIZE); |
2263 | kfree_skb(skb); | 2324 | kfree_skb(skb); |
2264 | goto errout; | 2325 | goto errout; |
2265 | } | 2326 | } |
2266 | err = rtnl_notify(skb, &init_net, info->pid, | 2327 | err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, |
2267 | RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any()); | 2328 | info->nlh, gfp_any()); |
2268 | errout: | 2329 | errout: |
2269 | if (err < 0) | 2330 | if (err < 0) |
2270 | rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err); | 2331 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
2332 | } | ||
2333 | |||
2334 | static int ip6_route_dev_notify(struct notifier_block *this, | ||
2335 | unsigned long event, void *data) | ||
2336 | { | ||
2337 | struct net_device *dev = (struct net_device *)data; | ||
2338 | struct net *net = dev_net(dev); | ||
2339 | |||
2340 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | ||
2341 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | ||
2342 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | ||
2343 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2344 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | ||
2345 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | ||
2346 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | ||
2347 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | ||
2348 | #endif | ||
2349 | } | ||
2350 | |||
2351 | return NOTIFY_OK; | ||
2271 | } | 2352 | } |
2272 | 2353 | ||
2273 | /* | 2354 | /* |
@@ -2316,13 +2397,33 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2316 | 2397 | ||
2317 | static int ipv6_route_show(struct seq_file *m, void *v) | 2398 | static int ipv6_route_show(struct seq_file *m, void *v) |
2318 | { | 2399 | { |
2319 | fib6_clean_all(rt6_info_route, 0, m); | 2400 | struct net *net = (struct net *)m->private; |
2401 | fib6_clean_all(net, rt6_info_route, 0, m); | ||
2320 | return 0; | 2402 | return 0; |
2321 | } | 2403 | } |
2322 | 2404 | ||
2323 | static int ipv6_route_open(struct inode *inode, struct file *file) | 2405 | static int ipv6_route_open(struct inode *inode, struct file *file) |
2324 | { | 2406 | { |
2325 | return single_open(file, ipv6_route_show, NULL); | 2407 | int err; |
2408 | struct net *net = get_proc_net(inode); | ||
2409 | if (!net) | ||
2410 | return -ENXIO; | ||
2411 | |||
2412 | err = single_open(file, ipv6_route_show, net); | ||
2413 | if (err < 0) { | ||
2414 | put_net(net); | ||
2415 | return err; | ||
2416 | } | ||
2417 | |||
2418 | return 0; | ||
2419 | } | ||
2420 | |||
2421 | static int ipv6_route_release(struct inode *inode, struct file *file) | ||
2422 | { | ||
2423 | struct seq_file *seq = file->private_data; | ||
2424 | struct net *net = seq->private; | ||
2425 | put_net(net); | ||
2426 | return single_release(inode, file); | ||
2326 | } | 2427 | } |
2327 | 2428 | ||
2328 | static const struct file_operations ipv6_route_proc_fops = { | 2429 | static const struct file_operations ipv6_route_proc_fops = { |
@@ -2330,24 +2431,46 @@ static const struct file_operations ipv6_route_proc_fops = { | |||
2330 | .open = ipv6_route_open, | 2431 | .open = ipv6_route_open, |
2331 | .read = seq_read, | 2432 | .read = seq_read, |
2332 | .llseek = seq_lseek, | 2433 | .llseek = seq_lseek, |
2333 | .release = single_release, | 2434 | .release = ipv6_route_release, |
2334 | }; | 2435 | }; |
2335 | 2436 | ||
2336 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) | 2437 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) |
2337 | { | 2438 | { |
2439 | struct net *net = (struct net *)seq->private; | ||
2338 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", | 2440 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", |
2339 | rt6_stats.fib_nodes, rt6_stats.fib_route_nodes, | 2441 | net->ipv6.rt6_stats->fib_nodes, |
2340 | rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries, | 2442 | net->ipv6.rt6_stats->fib_route_nodes, |
2341 | rt6_stats.fib_rt_cache, | 2443 | net->ipv6.rt6_stats->fib_rt_alloc, |
2342 | atomic_read(&ip6_dst_ops.entries), | 2444 | net->ipv6.rt6_stats->fib_rt_entries, |
2343 | rt6_stats.fib_discarded_routes); | 2445 | net->ipv6.rt6_stats->fib_rt_cache, |
2446 | atomic_read(&net->ipv6.ip6_dst_ops->entries), | ||
2447 | net->ipv6.rt6_stats->fib_discarded_routes); | ||
2344 | 2448 | ||
2345 | return 0; | 2449 | return 0; |
2346 | } | 2450 | } |
2347 | 2451 | ||
2348 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) | 2452 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) |
2349 | { | 2453 | { |
2350 | return single_open(file, rt6_stats_seq_show, NULL); | 2454 | int err; |
2455 | struct net *net = get_proc_net(inode); | ||
2456 | if (!net) | ||
2457 | return -ENXIO; | ||
2458 | |||
2459 | err = single_open(file, rt6_stats_seq_show, net); | ||
2460 | if (err < 0) { | ||
2461 | put_net(net); | ||
2462 | return err; | ||
2463 | } | ||
2464 | |||
2465 | return 0; | ||
2466 | } | ||
2467 | |||
2468 | static int rt6_stats_seq_release(struct inode *inode, struct file *file) | ||
2469 | { | ||
2470 | struct seq_file *seq = file->private_data; | ||
2471 | struct net *net = (struct net *)seq->private; | ||
2472 | put_net(net); | ||
2473 | return single_release(inode, file); | ||
2351 | } | 2474 | } |
2352 | 2475 | ||
2353 | static const struct file_operations rt6_stats_seq_fops = { | 2476 | static const struct file_operations rt6_stats_seq_fops = { |
@@ -2355,42 +2478,8 @@ static const struct file_operations rt6_stats_seq_fops = { | |||
2355 | .open = rt6_stats_seq_open, | 2478 | .open = rt6_stats_seq_open, |
2356 | .read = seq_read, | 2479 | .read = seq_read, |
2357 | .llseek = seq_lseek, | 2480 | .llseek = seq_lseek, |
2358 | .release = single_release, | 2481 | .release = rt6_stats_seq_release, |
2359 | }; | 2482 | }; |
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 */ | 2483 | #endif /* CONFIG_PROC_FS */ |
2395 | 2484 | ||
2396 | #ifdef CONFIG_SYSCTL | 2485 | #ifdef CONFIG_SYSCTL |
@@ -2399,10 +2488,11 @@ static | |||
2399 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, | 2488 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, |
2400 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2489 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2401 | { | 2490 | { |
2402 | int delay = init_net.ipv6.sysctl.flush_delay; | 2491 | struct net *net = current->nsproxy->net_ns; |
2492 | int delay = net->ipv6.sysctl.flush_delay; | ||
2403 | if (write) { | 2493 | if (write) { |
2404 | proc_dointvec(ctl, write, filp, buffer, lenp, ppos); | 2494 | proc_dointvec(ctl, write, filp, buffer, lenp, ppos); |
2405 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay); | 2495 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net); |
2406 | return 0; | 2496 | return 0; |
2407 | } else | 2497 | } else |
2408 | return -EINVAL; | 2498 | return -EINVAL; |
@@ -2419,7 +2509,7 @@ ctl_table ipv6_route_table_template[] = { | |||
2419 | { | 2509 | { |
2420 | .ctl_name = NET_IPV6_ROUTE_GC_THRESH, | 2510 | .ctl_name = NET_IPV6_ROUTE_GC_THRESH, |
2421 | .procname = "gc_thresh", | 2511 | .procname = "gc_thresh", |
2422 | .data = &ip6_dst_ops.gc_thresh, | 2512 | .data = &ip6_dst_ops_template.gc_thresh, |
2423 | .maxlen = sizeof(int), | 2513 | .maxlen = sizeof(int), |
2424 | .mode = 0644, | 2514 | .mode = 0644, |
2425 | .proc_handler = &proc_dointvec, | 2515 | .proc_handler = &proc_dointvec, |
@@ -2505,33 +2595,141 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) | |||
2505 | table = kmemdup(ipv6_route_table_template, | 2595 | table = kmemdup(ipv6_route_table_template, |
2506 | sizeof(ipv6_route_table_template), | 2596 | sizeof(ipv6_route_table_template), |
2507 | GFP_KERNEL); | 2597 | GFP_KERNEL); |
2598 | |||
2599 | if (table) { | ||
2600 | table[0].data = &net->ipv6.sysctl.flush_delay; | ||
2601 | table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh; | ||
2602 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; | ||
2603 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | ||
2604 | table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; | ||
2605 | table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval; | ||
2606 | table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
2607 | table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; | ||
2608 | table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; | ||
2609 | } | ||
2610 | |||
2508 | return table; | 2611 | return table; |
2509 | } | 2612 | } |
2510 | #endif | 2613 | #endif |
2511 | 2614 | ||
2615 | static int ip6_route_net_init(struct net *net) | ||
2616 | { | ||
2617 | int ret = 0; | ||
2618 | |||
2619 | ret = -ENOMEM; | ||
2620 | net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template, | ||
2621 | sizeof(*net->ipv6.ip6_dst_ops), | ||
2622 | GFP_KERNEL); | ||
2623 | if (!net->ipv6.ip6_dst_ops) | ||
2624 | goto out; | ||
2625 | net->ipv6.ip6_dst_ops->dst_net = net; | ||
2626 | |||
2627 | net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, | ||
2628 | sizeof(*net->ipv6.ip6_null_entry), | ||
2629 | GFP_KERNEL); | ||
2630 | if (!net->ipv6.ip6_null_entry) | ||
2631 | goto out_ip6_dst_ops; | ||
2632 | net->ipv6.ip6_null_entry->u.dst.path = | ||
2633 | (struct dst_entry *)net->ipv6.ip6_null_entry; | ||
2634 | net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2635 | |||
2636 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2637 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | ||
2638 | sizeof(*net->ipv6.ip6_prohibit_entry), | ||
2639 | GFP_KERNEL); | ||
2640 | if (!net->ipv6.ip6_prohibit_entry) { | ||
2641 | kfree(net->ipv6.ip6_null_entry); | ||
2642 | goto out; | ||
2643 | } | ||
2644 | net->ipv6.ip6_prohibit_entry->u.dst.path = | ||
2645 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | ||
2646 | net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2647 | |||
2648 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | ||
2649 | sizeof(*net->ipv6.ip6_blk_hole_entry), | ||
2650 | GFP_KERNEL); | ||
2651 | if (!net->ipv6.ip6_blk_hole_entry) { | ||
2652 | kfree(net->ipv6.ip6_null_entry); | ||
2653 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2654 | goto out; | ||
2655 | } | ||
2656 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | ||
2657 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | ||
2658 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; | ||
2659 | #endif | ||
2660 | |||
2661 | #ifdef CONFIG_PROC_FS | ||
2662 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2663 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2664 | #endif | ||
2665 | net->ipv6.ip6_rt_gc_expire = 30*HZ; | ||
2666 | |||
2667 | ret = 0; | ||
2668 | out: | ||
2669 | return ret; | ||
2670 | |||
2671 | out_ip6_dst_ops: | ||
2672 | kfree(net->ipv6.ip6_dst_ops); | ||
2673 | goto out; | ||
2674 | } | ||
2675 | |||
2676 | static void ip6_route_net_exit(struct net *net) | ||
2677 | { | ||
2678 | #ifdef CONFIG_PROC_FS | ||
2679 | proc_net_remove(net, "ipv6_route"); | ||
2680 | proc_net_remove(net, "rt6_stats"); | ||
2681 | #endif | ||
2682 | kfree(net->ipv6.ip6_null_entry); | ||
2683 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2684 | kfree(net->ipv6.ip6_prohibit_entry); | ||
2685 | kfree(net->ipv6.ip6_blk_hole_entry); | ||
2686 | #endif | ||
2687 | kfree(net->ipv6.ip6_dst_ops); | ||
2688 | } | ||
2689 | |||
2690 | static struct pernet_operations ip6_route_net_ops = { | ||
2691 | .init = ip6_route_net_init, | ||
2692 | .exit = ip6_route_net_exit, | ||
2693 | }; | ||
2694 | |||
2695 | static struct notifier_block ip6_route_dev_notifier = { | ||
2696 | .notifier_call = ip6_route_dev_notify, | ||
2697 | .priority = 0, | ||
2698 | }; | ||
2699 | |||
2512 | int __init ip6_route_init(void) | 2700 | int __init ip6_route_init(void) |
2513 | { | 2701 | { |
2514 | int ret; | 2702 | int ret; |
2515 | 2703 | ||
2516 | ip6_dst_ops.kmem_cachep = | 2704 | ret = -ENOMEM; |
2705 | ip6_dst_ops_template.kmem_cachep = | ||
2517 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, | 2706 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, |
2518 | SLAB_HWCACHE_ALIGN, NULL); | 2707 | SLAB_HWCACHE_ALIGN, NULL); |
2519 | if (!ip6_dst_ops.kmem_cachep) | 2708 | if (!ip6_dst_ops_template.kmem_cachep) |
2520 | return -ENOMEM; | 2709 | goto out;; |
2521 | |||
2522 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; | ||
2523 | 2710 | ||
2524 | ret = fib6_init(); | 2711 | ret = register_pernet_subsys(&ip6_route_net_ops); |
2525 | if (ret) | 2712 | if (ret) |
2526 | goto out_kmem_cache; | 2713 | goto out_kmem_cache; |
2527 | 2714 | ||
2528 | ret = ipv6_route_proc_init(&init_net); | 2715 | /* Registering of the loopback is done before this portion of code, |
2716 | * the loopback reference in rt6_info will not be taken, do it | ||
2717 | * manually for init_net */ | ||
2718 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | ||
2719 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2720 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2721 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | ||
2722 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2723 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | ||
2724 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | ||
2725 | #endif | ||
2726 | ret = fib6_init(); | ||
2529 | if (ret) | 2727 | if (ret) |
2530 | goto out_fib6_init; | 2728 | goto out_register_subsys; |
2531 | 2729 | ||
2532 | ret = xfrm6_init(); | 2730 | ret = xfrm6_init(); |
2533 | if (ret) | 2731 | if (ret) |
2534 | goto out_proc_init; | 2732 | goto out_fib6_init; |
2535 | 2733 | ||
2536 | ret = fib6_rules_init(); | 2734 | ret = fib6_rules_init(); |
2537 | if (ret) | 2735 | if (ret) |
@@ -2543,7 +2741,10 @@ int __init ip6_route_init(void) | |||
2543 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2741 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) |
2544 | goto fib6_rules_init; | 2742 | goto fib6_rules_init; |
2545 | 2743 | ||
2546 | ret = 0; | 2744 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
2745 | if (ret) | ||
2746 | goto fib6_rules_init; | ||
2747 | |||
2547 | out: | 2748 | out: |
2548 | return ret; | 2749 | return ret; |
2549 | 2750 | ||
@@ -2551,22 +2752,21 @@ fib6_rules_init: | |||
2551 | fib6_rules_cleanup(); | 2752 | fib6_rules_cleanup(); |
2552 | xfrm6_init: | 2753 | xfrm6_init: |
2553 | xfrm6_fini(); | 2754 | xfrm6_fini(); |
2554 | out_proc_init: | ||
2555 | ipv6_route_proc_fini(&init_net); | ||
2556 | out_fib6_init: | 2755 | out_fib6_init: |
2557 | rt6_ifdown(NULL); | ||
2558 | fib6_gc_cleanup(); | 2756 | fib6_gc_cleanup(); |
2757 | out_register_subsys: | ||
2758 | unregister_pernet_subsys(&ip6_route_net_ops); | ||
2559 | out_kmem_cache: | 2759 | out_kmem_cache: |
2560 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2760 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); |
2561 | goto out; | 2761 | goto out; |
2562 | } | 2762 | } |
2563 | 2763 | ||
2564 | void ip6_route_cleanup(void) | 2764 | void ip6_route_cleanup(void) |
2565 | { | 2765 | { |
2766 | unregister_netdevice_notifier(&ip6_route_dev_notifier); | ||
2566 | fib6_rules_cleanup(); | 2767 | fib6_rules_cleanup(); |
2567 | ipv6_route_proc_fini(&init_net); | ||
2568 | xfrm6_fini(); | 2768 | xfrm6_fini(); |
2569 | rt6_ifdown(NULL); | ||
2570 | fib6_gc_cleanup(); | 2769 | fib6_gc_cleanup(); |
2571 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); | 2770 | unregister_pernet_subsys(&ip6_route_net_ops); |
2771 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); | ||
2572 | } | 2772 | } |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1656c003b989..91e46fbe6ce2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * Changes: | 16 | * Changes: |
17 | * Roger Venning <r.venning@telstra.com>: 6to4 support | 17 | * Roger Venning <r.venning@telstra.com>: 6to4 support |
18 | * Nate Thompson <nate@thebog.net>: 6to4 support | 18 | * Nate Thompson <nate@thebog.net>: 6to4 support |
19 | * Fred L. Templin <fltemplin@acm.org>: isatap support | 19 | * Fred Templin <fred.l.templin@boeing.com>: isatap support |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
@@ -197,6 +197,179 @@ failed: | |||
197 | return NULL; | 197 | return NULL; |
198 | } | 198 | } |
199 | 199 | ||
200 | static struct ip_tunnel_prl_entry * | ||
201 | __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) | ||
202 | { | ||
203 | struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL; | ||
204 | |||
205 | for (p = t->prl; p; p = p->next) | ||
206 | if (p->addr == addr) | ||
207 | break; | ||
208 | return p; | ||
209 | |||
210 | } | ||
211 | |||
212 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | ||
213 | { | ||
214 | struct ip_tunnel_prl *kp; | ||
215 | struct ip_tunnel_prl_entry *prl; | ||
216 | unsigned int cmax, c = 0, ca, len; | ||
217 | int ret = 0; | ||
218 | |||
219 | cmax = a->datalen / sizeof(*a); | ||
220 | if (cmax > 1 && a->addr != htonl(INADDR_ANY)) | ||
221 | cmax = 1; | ||
222 | |||
223 | /* For simple GET or for root users, | ||
224 | * we try harder to allocate. | ||
225 | */ | ||
226 | kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ? | ||
227 | kcalloc(cmax, sizeof(*kp), GFP_KERNEL) : | ||
228 | NULL; | ||
229 | |||
230 | read_lock(&ipip6_lock); | ||
231 | |||
232 | ca = t->prl_count < cmax ? t->prl_count : cmax; | ||
233 | |||
234 | if (!kp) { | ||
235 | /* We don't try hard to allocate much memory for | ||
236 | * non-root users. | ||
237 | * For root users, retry allocating enough memory for | ||
238 | * the answer. | ||
239 | */ | ||
240 | kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC); | ||
241 | if (!kp) { | ||
242 | ret = -ENOMEM; | ||
243 | goto out; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | c = 0; | ||
248 | for (prl = t->prl; prl; prl = prl->next) { | ||
249 | if (c > cmax) | ||
250 | break; | ||
251 | if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr) | ||
252 | continue; | ||
253 | kp[c].addr = prl->addr; | ||
254 | kp[c].flags = prl->flags; | ||
255 | c++; | ||
256 | if (a->addr != htonl(INADDR_ANY)) | ||
257 | break; | ||
258 | } | ||
259 | out: | ||
260 | read_unlock(&ipip6_lock); | ||
261 | |||
262 | len = sizeof(*kp) * c; | ||
263 | ret = len ? copy_to_user(a->data, kp, len) : 0; | ||
264 | |||
265 | kfree(kp); | ||
266 | if (ret) | ||
267 | return -EFAULT; | ||
268 | |||
269 | a->datalen = len; | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int | ||
274 | ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | ||
275 | { | ||
276 | struct ip_tunnel_prl_entry *p; | ||
277 | int err = 0; | ||
278 | |||
279 | if (a->addr == htonl(INADDR_ANY)) | ||
280 | return -EINVAL; | ||
281 | |||
282 | write_lock(&ipip6_lock); | ||
283 | |||
284 | for (p = t->prl; p; p = p->next) { | ||
285 | if (p->addr == a->addr) { | ||
286 | if (chg) | ||
287 | goto update; | ||
288 | err = -EEXIST; | ||
289 | goto out; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | if (chg) { | ||
294 | err = -ENXIO; | ||
295 | goto out; | ||
296 | } | ||
297 | |||
298 | p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL); | ||
299 | if (!p) { | ||
300 | err = -ENOBUFS; | ||
301 | goto out; | ||
302 | } | ||
303 | |||
304 | p->next = t->prl; | ||
305 | t->prl = p; | ||
306 | t->prl_count++; | ||
307 | update: | ||
308 | p->addr = a->addr; | ||
309 | p->flags = a->flags; | ||
310 | out: | ||
311 | write_unlock(&ipip6_lock); | ||
312 | return err; | ||
313 | } | ||
314 | |||
315 | static int | ||
316 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | ||
317 | { | ||
318 | struct ip_tunnel_prl_entry *x, **p; | ||
319 | int err = 0; | ||
320 | |||
321 | write_lock(&ipip6_lock); | ||
322 | |||
323 | if (a && a->addr != htonl(INADDR_ANY)) { | ||
324 | for (p = &t->prl; *p; p = &(*p)->next) { | ||
325 | if ((*p)->addr == a->addr) { | ||
326 | x = *p; | ||
327 | *p = x->next; | ||
328 | kfree(x); | ||
329 | t->prl_count--; | ||
330 | goto out; | ||
331 | } | ||
332 | } | ||
333 | err = -ENXIO; | ||
334 | } else { | ||
335 | while (t->prl) { | ||
336 | x = t->prl; | ||
337 | t->prl = t->prl->next; | ||
338 | kfree(x); | ||
339 | t->prl_count--; | ||
340 | } | ||
341 | } | ||
342 | out: | ||
343 | write_unlock(&ipip6_lock); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int | ||
348 | isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) | ||
349 | { | ||
350 | struct ip_tunnel_prl_entry *p; | ||
351 | int ok = 1; | ||
352 | |||
353 | read_lock(&ipip6_lock); | ||
354 | p = __ipip6_tunnel_locate_prl(t, iph->saddr); | ||
355 | if (p) { | ||
356 | if (p->flags & PRL_DEFAULT) | ||
357 | skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT; | ||
358 | else | ||
359 | skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; | ||
360 | } else { | ||
361 | struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; | ||
362 | if (ipv6_addr_is_isatap(addr6) && | ||
363 | (addr6->s6_addr32[3] == iph->saddr) && | ||
364 | ipv6_chk_prefix(addr6, t->dev)) | ||
365 | skb->ndisc_nodetype = NDISC_NODETYPE_HOST; | ||
366 | else | ||
367 | ok = 0; | ||
368 | } | ||
369 | read_unlock(&ipip6_lock); | ||
370 | return ok; | ||
371 | } | ||
372 | |||
200 | static void ipip6_tunnel_uninit(struct net_device *dev) | 373 | static void ipip6_tunnel_uninit(struct net_device *dev) |
201 | { | 374 | { |
202 | if (dev == ipip6_fb_tunnel_dev) { | 375 | if (dev == ipip6_fb_tunnel_dev) { |
@@ -206,6 +379,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
206 | dev_put(dev); | 379 | dev_put(dev); |
207 | } else { | 380 | } else { |
208 | ipip6_tunnel_unlink(netdev_priv(dev)); | 381 | ipip6_tunnel_unlink(netdev_priv(dev)); |
382 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); | ||
209 | dev_put(dev); | 383 | dev_put(dev); |
210 | } | 384 | } |
211 | } | 385 | } |
@@ -339,11 +513,11 @@ out: | |||
339 | skb_reset_network_header(skb2); | 513 | skb_reset_network_header(skb2); |
340 | 514 | ||
341 | /* Try to guess incoming interface */ | 515 | /* Try to guess incoming interface */ |
342 | rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); | 516 | rt6i = rt6_lookup(&init_net, &iph6->saddr, NULL, NULL, 0); |
343 | if (rt6i && rt6i->rt6i_dev) { | 517 | if (rt6i && rt6i->rt6i_dev) { |
344 | skb2->dev = rt6i->rt6i_dev; | 518 | skb2->dev = rt6i->rt6i_dev; |
345 | 519 | ||
346 | rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); | 520 | rt6i = rt6_lookup(&init_net, &iph6->daddr, &iph6->saddr, NULL, 0); |
347 | 521 | ||
348 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { | 522 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { |
349 | struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); | 523 | struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); |
@@ -365,48 +539,6 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | |||
365 | IP6_ECN_set_ce(ipv6_hdr(skb)); | 539 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
366 | } | 540 | } |
367 | 541 | ||
368 | /* ISATAP (RFC4214) - check source address */ | ||
369 | static int | ||
370 | isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev) | ||
371 | { | ||
372 | struct neighbour *neigh; | ||
373 | struct dst_entry *dst; | ||
374 | struct rt6_info *rt; | ||
375 | struct flowi fl; | ||
376 | struct in6_addr *addr6; | ||
377 | struct in6_addr rtr; | ||
378 | struct ipv6hdr *iph6; | ||
379 | int ok = 0; | ||
380 | |||
381 | /* from onlink default router */ | ||
382 | ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0); | ||
383 | ipv6_isatap_eui64(rtr.s6_addr + 8, iph->saddr); | ||
384 | if ((rt = rt6_get_dflt_router(&rtr, dev))) { | ||
385 | dst_release(&rt->u.dst); | ||
386 | return 1; | ||
387 | } | ||
388 | |||
389 | iph6 = ipv6_hdr(skb); | ||
390 | memset(&fl, 0, sizeof(fl)); | ||
391 | fl.proto = iph6->nexthdr; | ||
392 | ipv6_addr_copy(&fl.fl6_dst, &iph6->saddr); | ||
393 | fl.oif = dev->ifindex; | ||
394 | security_skb_classify_flow(skb, &fl); | ||
395 | |||
396 | dst = ip6_route_output(NULL, &fl); | ||
397 | if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) { | ||
398 | |||
399 | addr6 = (struct in6_addr*)&neigh->primary_key; | ||
400 | |||
401 | /* from correct previous hop */ | ||
402 | if (ipv6_addr_is_isatap(addr6) && | ||
403 | (addr6->s6_addr32[3] == iph->saddr)) | ||
404 | ok = 1; | ||
405 | } | ||
406 | dst_release(dst); | ||
407 | return ok; | ||
408 | } | ||
409 | |||
410 | static int ipip6_rcv(struct sk_buff *skb) | 542 | static int ipip6_rcv(struct sk_buff *skb) |
411 | { | 543 | { |
412 | struct iphdr *iph; | 544 | struct iphdr *iph; |
@@ -427,7 +559,7 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
427 | skb->pkt_type = PACKET_HOST; | 559 | skb->pkt_type = PACKET_HOST; |
428 | 560 | ||
429 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && | 561 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && |
430 | !isatap_srcok(skb, iph, tunnel->dev)) { | 562 | !isatap_chksrc(skb, iph, tunnel)) { |
431 | tunnel->stat.rx_errors++; | 563 | tunnel->stat.rx_errors++; |
432 | read_unlock(&ipip6_lock); | 564 | read_unlock(&ipip6_lock); |
433 | kfree_skb(skb); | 565 | kfree_skb(skb); |
@@ -707,6 +839,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
707 | { | 839 | { |
708 | int err = 0; | 840 | int err = 0; |
709 | struct ip_tunnel_parm p; | 841 | struct ip_tunnel_parm p; |
842 | struct ip_tunnel_prl prl; | ||
710 | struct ip_tunnel *t; | 843 | struct ip_tunnel *t; |
711 | 844 | ||
712 | switch (cmd) { | 845 | switch (cmd) { |
@@ -806,6 +939,42 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
806 | err = 0; | 939 | err = 0; |
807 | break; | 940 | break; |
808 | 941 | ||
942 | case SIOCGETPRL: | ||
943 | case SIOCADDPRL: | ||
944 | case SIOCDELPRL: | ||
945 | case SIOCCHGPRL: | ||
946 | err = -EPERM; | ||
947 | if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) | ||
948 | goto done; | ||
949 | err = -EINVAL; | ||
950 | if (dev == ipip6_fb_tunnel_dev) | ||
951 | goto done; | ||
952 | err = -EFAULT; | ||
953 | if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) | ||
954 | goto done; | ||
955 | err = -ENOENT; | ||
956 | if (!(t = netdev_priv(dev))) | ||
957 | goto done; | ||
958 | |||
959 | switch (cmd) { | ||
960 | case SIOCGETPRL: | ||
961 | err = ipip6_tunnel_get_prl(t, &prl); | ||
962 | if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, | ||
963 | &prl, sizeof(prl))) | ||
964 | err = -EFAULT; | ||
965 | break; | ||
966 | case SIOCDELPRL: | ||
967 | err = ipip6_tunnel_del_prl(t, &prl); | ||
968 | break; | ||
969 | case SIOCADDPRL: | ||
970 | case SIOCCHGPRL: | ||
971 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | ||
972 | break; | ||
973 | } | ||
974 | if (cmd != SIOCGETPRL) | ||
975 | netdev_state_change(dev); | ||
976 | break; | ||
977 | |||
809 | default: | 978 | default: |
810 | err = -EINVAL; | 979 | err = -EINVAL; |
811 | } | 980 | } |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c new file mode 100644 index 000000000000..938ce4ecde55 --- /dev/null +++ b/net/ipv6/syncookies.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * IPv6 Syncookies implementation for the Linux kernel | ||
3 | * | ||
4 | * Authors: | ||
5 | * Glenn Griffin <ggriffin.kernel@gmail.com> | ||
6 | * | ||
7 | * Based on IPv4 implementation by Andi Kleen | ||
8 | * linux/net/ipv4/syncookies.c | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/tcp.h> | ||
18 | #include <linux/random.h> | ||
19 | #include <linux/cryptohash.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <net/ipv6.h> | ||
22 | #include <net/tcp.h> | ||
23 | |||
24 | extern int sysctl_tcp_syncookies; | ||
25 | extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | ||
26 | |||
27 | #define COOKIEBITS 24 /* Upper bits store count */ | ||
28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | ||
29 | |||
30 | /* | ||
31 | * This table has to be sorted and terminated with (__u16)-1. | ||
32 | * XXX generate a better table. | ||
33 | * Unresolved Issues: HIPPI with a 64k MSS is not well supported. | ||
34 | * | ||
35 | * Taken directly from ipv4 implementation. | ||
36 | * Should this list be modified for ipv6 use or is it close enough? | ||
37 | * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart | ||
38 | */ | ||
39 | static __u16 const msstab[] = { | ||
40 | 64 - 1, | ||
41 | 256 - 1, | ||
42 | 512 - 1, | ||
43 | 536 - 1, | ||
44 | 1024 - 1, | ||
45 | 1440 - 1, | ||
46 | 1460 - 1, | ||
47 | 4312 - 1, | ||
48 | (__u16)-1 | ||
49 | }; | ||
50 | /* The number doesn't include the -1 terminator */ | ||
51 | #define NUM_MSS (ARRAY_SIZE(msstab) - 1) | ||
52 | |||
53 | /* | ||
54 | * This (misnamed) value is the age of syncookie which is permitted. | ||
55 | * Its ideal value should be dependent on TCP_TIMEOUT_INIT and | ||
56 | * sysctl_tcp_retries1. It's a rather complicated formula (exponential | ||
57 | * backoff) to compute at runtime so it's currently hardcoded here. | ||
58 | */ | ||
59 | #define COUNTER_TRIES 4 | ||
60 | |||
61 | static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | ||
62 | struct request_sock *req, | ||
63 | struct dst_entry *dst) | ||
64 | { | ||
65 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
66 | struct sock *child; | ||
67 | |||
68 | child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst); | ||
69 | if (child) | ||
70 | inet_csk_reqsk_queue_add(sk, req, child); | ||
71 | else | ||
72 | reqsk_free(req); | ||
73 | |||
74 | return child; | ||
75 | } | ||
76 | |||
77 | static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS]; | ||
78 | |||
79 | static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr, | ||
80 | __be16 sport, __be16 dport, u32 count, int c) | ||
81 | { | ||
82 | __u32 *tmp = __get_cpu_var(cookie_scratch); | ||
83 | |||
84 | /* | ||
85 | * we have 320 bits of information to hash, copy in the remaining | ||
86 | * 192 bits required for sha_transform, from the syncookie_secret | ||
87 | * and overwrite the digest with the secret | ||
88 | */ | ||
89 | memcpy(tmp + 10, syncookie_secret[c], 44); | ||
90 | memcpy(tmp, saddr, 16); | ||
91 | memcpy(tmp + 4, daddr, 16); | ||
92 | tmp[8] = ((__force u32)sport << 16) + (__force u32)dport; | ||
93 | tmp[9] = count; | ||
94 | sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); | ||
95 | |||
96 | return tmp[17]; | ||
97 | } | ||
98 | |||
99 | static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *daddr, | ||
100 | __be16 sport, __be16 dport, __u32 sseq, | ||
101 | __u32 count, __u32 data) | ||
102 | { | ||
103 | return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + | ||
104 | sseq + (count << COOKIEBITS) + | ||
105 | ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) | ||
106 | & COOKIEMASK)); | ||
107 | } | ||
108 | |||
109 | static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr, | ||
110 | struct in6_addr *daddr, __be16 sport, | ||
111 | __be16 dport, __u32 sseq, __u32 count, | ||
112 | __u32 maxdiff) | ||
113 | { | ||
114 | __u32 diff; | ||
115 | |||
116 | cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; | ||
117 | |||
118 | diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS); | ||
119 | if (diff >= maxdiff) | ||
120 | return (__u32)-1; | ||
121 | |||
122 | return (cookie - | ||
123 | cookie_hash(saddr, daddr, sport, dport, count - diff, 1)) | ||
124 | & COOKIEMASK; | ||
125 | } | ||
126 | |||
127 | __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | ||
128 | { | ||
129 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
130 | const struct tcphdr *th = tcp_hdr(skb); | ||
131 | int mssind; | ||
132 | const __u16 mss = *mssp; | ||
133 | |||
134 | tcp_sk(sk)->last_synq_overflow = jiffies; | ||
135 | |||
136 | for (mssind = 0; mss > msstab[mssind + 1]; mssind++) | ||
137 | ; | ||
138 | *mssp = msstab[mssind] + 1; | ||
139 | |||
140 | NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESSENT); | ||
141 | |||
142 | return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source, | ||
143 | th->dest, ntohl(th->seq), | ||
144 | jiffies / (HZ * 60), mssind); | ||
145 | } | ||
146 | |||
147 | static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | ||
148 | { | ||
149 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
150 | const struct tcphdr *th = tcp_hdr(skb); | ||
151 | __u32 seq = ntohl(th->seq) - 1; | ||
152 | __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, | ||
153 | th->source, th->dest, seq, | ||
154 | jiffies / (HZ * 60), COUNTER_TRIES); | ||
155 | |||
156 | return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; | ||
157 | } | ||
158 | |||
159 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | ||
160 | { | ||
161 | struct inet_request_sock *ireq; | ||
162 | struct inet6_request_sock *ireq6; | ||
163 | struct tcp_request_sock *treq; | ||
164 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
165 | struct tcp_sock *tp = tcp_sk(sk); | ||
166 | const struct tcphdr *th = tcp_hdr(skb); | ||
167 | __u32 cookie = ntohl(th->ack_seq) - 1; | ||
168 | struct sock *ret = sk; | ||
169 | struct request_sock *req; | ||
170 | int mss; | ||
171 | struct dst_entry *dst; | ||
172 | __u8 rcv_wscale; | ||
173 | struct tcp_options_received tcp_opt; | ||
174 | |||
175 | if (!sysctl_tcp_syncookies || !th->ack) | ||
176 | goto out; | ||
177 | |||
178 | if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || | ||
179 | (mss = cookie_check(skb, cookie)) == 0) { | ||
180 | NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED); | ||
181 | goto out; | ||
182 | } | ||
183 | |||
184 | NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); | ||
185 | |||
186 | /* check for timestamp cookie support */ | ||
187 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | ||
188 | tcp_parse_options(skb, &tcp_opt, 0); | ||
189 | |||
190 | if (tcp_opt.saw_tstamp) | ||
191 | cookie_check_timestamp(&tcp_opt); | ||
192 | |||
193 | ret = NULL; | ||
194 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | ||
195 | if (!req) | ||
196 | goto out; | ||
197 | |||
198 | ireq = inet_rsk(req); | ||
199 | ireq6 = inet6_rsk(req); | ||
200 | treq = tcp_rsk(req); | ||
201 | ireq6->pktopts = NULL; | ||
202 | |||
203 | if (security_inet_conn_request(sk, skb, req)) { | ||
204 | reqsk_free(req); | ||
205 | goto out; | ||
206 | } | ||
207 | |||
208 | req->mss = mss; | ||
209 | ireq->rmt_port = th->source; | ||
210 | ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr); | ||
211 | ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr); | ||
212 | if (ipv6_opt_accepted(sk, skb) || | ||
213 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
214 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | ||
215 | atomic_inc(&skb->users); | ||
216 | ireq6->pktopts = skb; | ||
217 | } | ||
218 | |||
219 | ireq6->iif = sk->sk_bound_dev_if; | ||
220 | /* So that link locals have meaning */ | ||
221 | if (!sk->sk_bound_dev_if && | ||
222 | ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL) | ||
223 | ireq6->iif = inet6_iif(skb); | ||
224 | |||
225 | req->expires = 0UL; | ||
226 | req->retrans = 0; | ||
227 | ireq->snd_wscale = tcp_opt.snd_wscale; | ||
228 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
229 | ireq->sack_ok = tcp_opt.sack_ok; | ||
230 | ireq->wscale_ok = tcp_opt.wscale_ok; | ||
231 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | ||
232 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | ||
233 | treq->rcv_isn = ntohl(th->seq) - 1; | ||
234 | treq->snt_isn = cookie; | ||
235 | |||
236 | /* | ||
237 | * We need to lookup the dst_entry to get the correct window size. | ||
238 | * This is taken from tcp_v6_syn_recv_sock. Somebody please enlighten | ||
239 | * me if there is a preferred way. | ||
240 | */ | ||
241 | { | ||
242 | struct in6_addr *final_p = NULL, final; | ||
243 | struct flowi fl; | ||
244 | memset(&fl, 0, sizeof(fl)); | ||
245 | fl.proto = IPPROTO_TCP; | ||
246 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | ||
247 | if (np->opt && np->opt->srcrt) { | ||
248 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
249 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
250 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
251 | final_p = &final; | ||
252 | } | ||
253 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | ||
254 | fl.oif = sk->sk_bound_dev_if; | ||
255 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | ||
256 | fl.fl_ip_sport = inet_sk(sk)->sport; | ||
257 | security_req_classify_flow(req, &fl); | ||
258 | if (ip6_dst_lookup(sk, &dst, &fl)) { | ||
259 | reqsk_free(req); | ||
260 | goto out; | ||
261 | } | ||
262 | if (final_p) | ||
263 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
264 | if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
265 | goto out; | ||
266 | } | ||
267 | |||
268 | req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); | ||
269 | tcp_select_initial_window(tcp_full_space(sk), req->mss, | ||
270 | &req->rcv_wnd, &req->window_clamp, | ||
271 | ireq->wscale_ok, &rcv_wscale); | ||
272 | |||
273 | ireq->rcv_wscale = rcv_wscale; | ||
274 | |||
275 | ret = get_cookie_sock(sk, skb, req, dst); | ||
276 | |||
277 | out: return ret; | ||
278 | } | ||
279 | |||
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..231c4dddfb8c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <net/dsfield.h> | 60 | #include <net/dsfield.h> |
61 | #include <net/timewait_sock.h> | 61 | #include <net/timewait_sock.h> |
62 | #include <net/netdma.h> | 62 | #include <net/netdma.h> |
63 | #include <net/inet_common.h> | ||
63 | 64 | ||
64 | #include <asm/uaccess.h> | 65 | #include <asm/uaccess.h> |
65 | 66 | ||
@@ -69,9 +70,6 @@ | |||
69 | #include <linux/crypto.h> | 70 | #include <linux/crypto.h> |
70 | #include <linux/scatterlist.h> | 71 | #include <linux/scatterlist.h> |
71 | 72 | ||
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); | 73 | 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); | 74 | 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, | 75 | static void tcp_v6_send_check(struct sock *sk, int len, |
@@ -324,7 +322,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
324 | struct tcp_sock *tp; | 322 | struct tcp_sock *tp; |
325 | __u32 seq; | 323 | __u32 seq; |
326 | 324 | ||
327 | sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr, | 325 | sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr, |
328 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 326 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); |
329 | 327 | ||
330 | if (sk == NULL) { | 328 | if (sk == NULL) { |
@@ -455,8 +453,7 @@ out: | |||
455 | } | 453 | } |
456 | 454 | ||
457 | 455 | ||
458 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | 456 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) |
459 | struct dst_entry *dst) | ||
460 | { | 457 | { |
461 | struct inet6_request_sock *treq = inet6_rsk(req); | 458 | struct inet6_request_sock *treq = inet6_rsk(req); |
462 | struct ipv6_pinfo *np = inet6_sk(sk); | 459 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -464,6 +461,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
464 | struct ipv6_txoptions *opt = NULL; | 461 | struct ipv6_txoptions *opt = NULL; |
465 | struct in6_addr * final_p = NULL, final; | 462 | struct in6_addr * final_p = NULL, final; |
466 | struct flowi fl; | 463 | struct flowi fl; |
464 | struct dst_entry *dst; | ||
467 | int err = -1; | 465 | int err = -1; |
468 | 466 | ||
469 | memset(&fl, 0, sizeof(fl)); | 467 | memset(&fl, 0, sizeof(fl)); |
@@ -476,24 +474,22 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
476 | fl.fl_ip_sport = inet_sk(sk)->sport; | 474 | fl.fl_ip_sport = inet_sk(sk)->sport; |
477 | security_req_classify_flow(req, &fl); | 475 | security_req_classify_flow(req, &fl); |
478 | 476 | ||
479 | if (dst == NULL) { | 477 | opt = np->opt; |
480 | opt = np->opt; | 478 | if (opt && opt->srcrt) { |
481 | if (opt && opt->srcrt) { | 479 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
482 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 480 | ipv6_addr_copy(&final, &fl.fl6_dst); |
483 | ipv6_addr_copy(&final, &fl.fl6_dst); | 481 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
484 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | 482 | 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 | } | 483 | } |
496 | 484 | ||
485 | err = ip6_dst_lookup(sk, &dst, &fl); | ||
486 | if (err) | ||
487 | goto done; | ||
488 | if (final_p) | ||
489 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
490 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
491 | goto done; | ||
492 | |||
497 | skb = tcp_make_synack(sk, dst, req); | 493 | skb = tcp_make_synack(sk, dst, req); |
498 | if (skb) { | 494 | if (skb) { |
499 | struct tcphdr *th = tcp_hdr(skb); | 495 | struct tcphdr *th = tcp_hdr(skb); |
@@ -514,6 +510,20 @@ done: | |||
514 | return err; | 510 | return err; |
515 | } | 511 | } |
516 | 512 | ||
513 | static inline void syn_flood_warning(struct sk_buff *skb) | ||
514 | { | ||
515 | #ifdef CONFIG_SYN_COOKIES | ||
516 | if (sysctl_tcp_syncookies) | ||
517 | printk(KERN_INFO | ||
518 | "TCPv6: Possible SYN flooding on port %d. " | ||
519 | "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest)); | ||
520 | else | ||
521 | #endif | ||
522 | printk(KERN_INFO | ||
523 | "TCPv6: Possible SYN flooding on port %d. " | ||
524 | "Dropping request.\n", ntohs(tcp_hdr(skb)->dest)); | ||
525 | } | ||
526 | |||
517 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 527 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
518 | { | 528 | { |
519 | if (inet6_rsk(req)->pktopts) | 529 | if (inet6_rsk(req)->pktopts) |
@@ -533,7 +543,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
533 | return NULL; | 543 | return NULL; |
534 | 544 | ||
535 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 545 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
536 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) | 546 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr)) |
537 | return &tp->md5sig_info->keys6[i].base; | 547 | return &tp->md5sig_info->keys6[i].base; |
538 | } | 548 | } |
539 | return NULL; | 549 | return NULL; |
@@ -622,7 +632,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | |||
622 | int i; | 632 | int i; |
623 | 633 | ||
624 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 634 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
625 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { | 635 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) { |
626 | /* Free the key */ | 636 | /* Free the key */ |
627 | kfree(tp->md5sig_info->keys6[i].base.key); | 637 | kfree(tp->md5sig_info->keys6[i].base.key); |
628 | tp->md5sig_info->entries6--; | 638 | tp->md5sig_info->entries6--; |
@@ -741,7 +751,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
741 | 751 | ||
742 | hp = tcp_get_md5sig_pool(); | 752 | hp = tcp_get_md5sig_pool(); |
743 | if (!hp) { | 753 | if (!hp) { |
744 | printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__); | 754 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); |
745 | goto clear_hash_noput; | 755 | goto clear_hash_noput; |
746 | } | 756 | } |
747 | bp = &hp->md5_blk.ip6; | 757 | bp = &hp->md5_blk.ip6; |
@@ -781,17 +791,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 */ | 791 | /* Now store the hash into the packet */ |
782 | err = crypto_hash_init(desc); | 792 | err = crypto_hash_init(desc); |
783 | if (err) { | 793 | if (err) { |
784 | printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__); | 794 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); |
785 | goto clear_hash; | 795 | goto clear_hash; |
786 | } | 796 | } |
787 | err = crypto_hash_update(desc, sg, nbytes); | 797 | err = crypto_hash_update(desc, sg, nbytes); |
788 | if (err) { | 798 | if (err) { |
789 | printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__); | 799 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); |
790 | goto clear_hash; | 800 | goto clear_hash; |
791 | } | 801 | } |
792 | err = crypto_hash_final(desc, md5_hash); | 802 | err = crypto_hash_final(desc, md5_hash); |
793 | if (err) { | 803 | if (err) { |
794 | printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__); | 804 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); |
795 | goto clear_hash; | 805 | goto clear_hash; |
796 | } | 806 | } |
797 | 807 | ||
@@ -917,7 +927,7 @@ done_opts: | |||
917 | } | 927 | } |
918 | #endif | 928 | #endif |
919 | 929 | ||
920 | static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 930 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
921 | .family = AF_INET6, | 931 | .family = AF_INET6, |
922 | .obj_size = sizeof(struct tcp6_request_sock), | 932 | .obj_size = sizeof(struct tcp6_request_sock), |
923 | .rtx_syn_ack = tcp_v6_send_synack, | 933 | .rtx_syn_ack = tcp_v6_send_synack, |
@@ -979,6 +989,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
979 | struct tcphdr *th = tcp_hdr(skb), *t1; | 989 | struct tcphdr *th = tcp_hdr(skb), *t1; |
980 | struct sk_buff *buff; | 990 | struct sk_buff *buff; |
981 | struct flowi fl; | 991 | struct flowi fl; |
992 | struct net *net = dev_net(skb->dst->dev); | ||
993 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
982 | unsigned int tot_len = sizeof(*th); | 994 | unsigned int tot_len = sizeof(*th); |
983 | #ifdef CONFIG_TCP_MD5SIG | 995 | #ifdef CONFIG_TCP_MD5SIG |
984 | struct tcp_md5sig_key *key; | 996 | struct tcp_md5sig_key *key; |
@@ -1059,11 +1071,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1059 | fl.fl_ip_sport = t1->source; | 1071 | fl.fl_ip_sport = t1->source; |
1060 | security_skb_classify_flow(skb, &fl); | 1072 | security_skb_classify_flow(skb, &fl); |
1061 | 1073 | ||
1062 | /* sk = NULL, but it is safe for now. RST socket required. */ | 1074 | /* Pass a socket to ip6_dst_lookup either it is for RST |
1063 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1075 | * Underlying function will use this to retrieve the network |
1076 | * namespace | ||
1077 | */ | ||
1078 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { | ||
1064 | 1079 | ||
1065 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1080 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1066 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1081 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1067 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1082 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1068 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); | 1083 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); |
1069 | return; | 1084 | return; |
@@ -1079,6 +1094,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1079 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1094 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1080 | struct sk_buff *buff; | 1095 | struct sk_buff *buff; |
1081 | struct flowi fl; | 1096 | struct flowi fl; |
1097 | struct net *net = dev_net(skb->dev); | ||
1098 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
1082 | unsigned int tot_len = sizeof(struct tcphdr); | 1099 | unsigned int tot_len = sizeof(struct tcphdr); |
1083 | __be32 *topt; | 1100 | __be32 *topt; |
1084 | #ifdef CONFIG_TCP_MD5SIG | 1101 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1160,9 +1177,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1160 | fl.fl_ip_sport = t1->source; | 1177 | fl.fl_ip_sport = t1->source; |
1161 | security_skb_classify_flow(skb, &fl); | 1178 | security_skb_classify_flow(skb, &fl); |
1162 | 1179 | ||
1163 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1180 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { |
1164 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1181 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1165 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1182 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1166 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1183 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1167 | return; | 1184 | return; |
1168 | } | 1185 | } |
@@ -1202,7 +1219,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1202 | if (req) | 1219 | if (req) |
1203 | return tcp_check_req(sk, skb, req, prev); | 1220 | return tcp_check_req(sk, skb, req, prev); |
1204 | 1221 | ||
1205 | nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo, | 1222 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |
1206 | &ipv6_hdr(skb)->saddr, th->source, | 1223 | &ipv6_hdr(skb)->saddr, th->source, |
1207 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); | 1224 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); |
1208 | 1225 | ||
@@ -1215,9 +1232,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1215 | return NULL; | 1232 | return NULL; |
1216 | } | 1233 | } |
1217 | 1234 | ||
1218 | #if 0 /*def CONFIG_SYN_COOKIES*/ | 1235 | #ifdef CONFIG_SYN_COOKIES |
1219 | if (!th->rst && !th->syn && th->ack) | 1236 | if (!th->rst && !th->syn && th->ack) |
1220 | sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt)); | 1237 | sk = cookie_v6_check(sk, skb); |
1221 | #endif | 1238 | #endif |
1222 | return sk; | 1239 | return sk; |
1223 | } | 1240 | } |
@@ -1233,6 +1250,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1233 | struct tcp_sock *tp = tcp_sk(sk); | 1250 | struct tcp_sock *tp = tcp_sk(sk); |
1234 | struct request_sock *req = NULL; | 1251 | struct request_sock *req = NULL; |
1235 | __u32 isn = TCP_SKB_CB(skb)->when; | 1252 | __u32 isn = TCP_SKB_CB(skb)->when; |
1253 | #ifdef CONFIG_SYN_COOKIES | ||
1254 | int want_cookie = 0; | ||
1255 | #else | ||
1256 | #define want_cookie 0 | ||
1257 | #endif | ||
1236 | 1258 | ||
1237 | if (skb->protocol == htons(ETH_P_IP)) | 1259 | if (skb->protocol == htons(ETH_P_IP)) |
1238 | return tcp_v4_conn_request(sk, skb); | 1260 | return tcp_v4_conn_request(sk, skb); |
@@ -1240,12 +1262,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1240 | if (!ipv6_unicast_destination(skb)) | 1262 | if (!ipv6_unicast_destination(skb)) |
1241 | goto drop; | 1263 | goto drop; |
1242 | 1264 | ||
1243 | /* | ||
1244 | * There are no SYN attacks on IPv6, yet... | ||
1245 | */ | ||
1246 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { | 1265 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
1247 | if (net_ratelimit()) | 1266 | if (net_ratelimit()) |
1248 | printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n"); | 1267 | syn_flood_warning(skb); |
1268 | #ifdef CONFIG_SYN_COOKIES | ||
1269 | if (sysctl_tcp_syncookies) | ||
1270 | want_cookie = 1; | ||
1271 | else | ||
1272 | #endif | ||
1249 | goto drop; | 1273 | goto drop; |
1250 | } | 1274 | } |
1251 | 1275 | ||
@@ -1266,39 +1290,50 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1266 | 1290 | ||
1267 | tcp_parse_options(skb, &tmp_opt, 0); | 1291 | tcp_parse_options(skb, &tmp_opt, 0); |
1268 | 1292 | ||
1293 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
1294 | tcp_clear_options(&tmp_opt); | ||
1295 | |||
1269 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | 1296 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; |
1270 | tcp_openreq_init(req, &tmp_opt, skb); | 1297 | tcp_openreq_init(req, &tmp_opt, skb); |
1271 | 1298 | ||
1272 | treq = inet6_rsk(req); | 1299 | treq = inet6_rsk(req); |
1273 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1300 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1274 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1301 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1275 | TCP_ECN_create_request(req, tcp_hdr(skb)); | ||
1276 | treq->pktopts = NULL; | 1302 | treq->pktopts = NULL; |
1277 | if (ipv6_opt_accepted(sk, skb) || | 1303 | if (!want_cookie) |
1278 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1304 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1279 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 1305 | |
1280 | atomic_inc(&skb->users); | 1306 | if (want_cookie) { |
1281 | treq->pktopts = skb; | 1307 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); |
1282 | } | 1308 | req->cookie_ts = tmp_opt.tstamp_ok; |
1283 | treq->iif = sk->sk_bound_dev_if; | 1309 | } else if (!isn) { |
1310 | if (ipv6_opt_accepted(sk, skb) || | ||
1311 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
1312 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | ||
1313 | atomic_inc(&skb->users); | ||
1314 | treq->pktopts = skb; | ||
1315 | } | ||
1316 | treq->iif = sk->sk_bound_dev_if; | ||
1284 | 1317 | ||
1285 | /* So that link locals have meaning */ | 1318 | /* So that link locals have meaning */ |
1286 | if (!sk->sk_bound_dev_if && | 1319 | if (!sk->sk_bound_dev_if && |
1287 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1320 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1288 | treq->iif = inet6_iif(skb); | 1321 | treq->iif = inet6_iif(skb); |
1289 | 1322 | ||
1290 | if (isn == 0) | ||
1291 | isn = tcp_v6_init_sequence(skb); | 1323 | isn = tcp_v6_init_sequence(skb); |
1324 | } | ||
1292 | 1325 | ||
1293 | tcp_rsk(req)->snt_isn = isn; | 1326 | tcp_rsk(req)->snt_isn = isn; |
1294 | 1327 | ||
1295 | security_inet_conn_request(sk, skb, req); | 1328 | security_inet_conn_request(sk, skb, req); |
1296 | 1329 | ||
1297 | if (tcp_v6_send_synack(sk, req, NULL)) | 1330 | if (tcp_v6_send_synack(sk, req)) |
1298 | goto drop; | 1331 | goto drop; |
1299 | 1332 | ||
1300 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1333 | if (!want_cookie) { |
1301 | return 0; | 1334 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1335 | return 0; | ||
1336 | } | ||
1302 | 1337 | ||
1303 | drop: | 1338 | drop: |
1304 | if (req) | 1339 | if (req) |
@@ -1704,7 +1739,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1704 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1739 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); |
1705 | TCP_SKB_CB(skb)->sacked = 0; | 1740 | TCP_SKB_CB(skb)->sacked = 0; |
1706 | 1741 | ||
1707 | sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, | 1742 | sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, |
1708 | &ipv6_hdr(skb)->saddr, th->source, | 1743 | &ipv6_hdr(skb)->saddr, th->source, |
1709 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), | 1744 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), |
1710 | inet6_iif(skb)); | 1745 | inet6_iif(skb)); |
@@ -1787,7 +1822,7 @@ do_time_wait: | |||
1787 | { | 1822 | { |
1788 | struct sock *sk2; | 1823 | struct sock *sk2; |
1789 | 1824 | ||
1790 | sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo, | 1825 | sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, |
1791 | &ipv6_hdr(skb)->daddr, | 1826 | &ipv6_hdr(skb)->daddr, |
1792 | ntohs(th->dest), inet6_iif(skb)); | 1827 | ntohs(th->dest), inet6_iif(skb)); |
1793 | if (sk2 != NULL) { | 1828 | if (sk2 != NULL) { |
@@ -2085,28 +2120,28 @@ out: | |||
2085 | return 0; | 2120 | return 0; |
2086 | } | 2121 | } |
2087 | 2122 | ||
2088 | static struct file_operations tcp6_seq_fops; | ||
2089 | static struct tcp_seq_afinfo tcp6_seq_afinfo = { | 2123 | static struct tcp_seq_afinfo tcp6_seq_afinfo = { |
2090 | .owner = THIS_MODULE, | ||
2091 | .name = "tcp6", | 2124 | .name = "tcp6", |
2092 | .family = AF_INET6, | 2125 | .family = AF_INET6, |
2093 | .seq_show = tcp6_seq_show, | 2126 | .seq_fops = { |
2094 | .seq_fops = &tcp6_seq_fops, | 2127 | .owner = THIS_MODULE, |
2128 | }, | ||
2129 | .seq_ops = { | ||
2130 | .show = tcp6_seq_show, | ||
2131 | }, | ||
2095 | }; | 2132 | }; |
2096 | 2133 | ||
2097 | int __init tcp6_proc_init(void) | 2134 | int tcp6_proc_init(struct net *net) |
2098 | { | 2135 | { |
2099 | return tcp_proc_register(&tcp6_seq_afinfo); | 2136 | return tcp_proc_register(net, &tcp6_seq_afinfo); |
2100 | } | 2137 | } |
2101 | 2138 | ||
2102 | void tcp6_proc_exit(void) | 2139 | void tcp6_proc_exit(struct net *net) |
2103 | { | 2140 | { |
2104 | tcp_proc_unregister(&tcp6_seq_afinfo); | 2141 | tcp_proc_unregister(net, &tcp6_seq_afinfo); |
2105 | } | 2142 | } |
2106 | #endif | 2143 | #endif |
2107 | 2144 | ||
2108 | DEFINE_PROTO_INUSE(tcpv6) | ||
2109 | |||
2110 | struct proto tcpv6_prot = { | 2145 | struct proto tcpv6_prot = { |
2111 | .name = "TCPv6", | 2146 | .name = "TCPv6", |
2112 | .owner = THIS_MODULE, | 2147 | .owner = THIS_MODULE, |
@@ -2137,12 +2172,11 @@ 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, |
2144 | #endif | 2179 | #endif |
2145 | REF_PROTO_INUSE(tcpv6) | ||
2146 | }; | 2180 | }; |
2147 | 2181 | ||
2148 | static struct inet6_protocol tcpv6_protocol = { | 2182 | static struct inet6_protocol tcpv6_protocol = { |
@@ -2164,6 +2198,22 @@ static struct inet_protosw tcpv6_protosw = { | |||
2164 | INET_PROTOSW_ICSK, | 2198 | INET_PROTOSW_ICSK, |
2165 | }; | 2199 | }; |
2166 | 2200 | ||
2201 | static int tcpv6_net_init(struct net *net) | ||
2202 | { | ||
2203 | return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6, | ||
2204 | SOCK_RAW, IPPROTO_TCP, net); | ||
2205 | } | ||
2206 | |||
2207 | static void tcpv6_net_exit(struct net *net) | ||
2208 | { | ||
2209 | inet_ctl_sock_destroy(net->ipv6.tcp_sk); | ||
2210 | } | ||
2211 | |||
2212 | static struct pernet_operations tcpv6_net_ops = { | ||
2213 | .init = tcpv6_net_init, | ||
2214 | .exit = tcpv6_net_exit, | ||
2215 | }; | ||
2216 | |||
2167 | int __init tcpv6_init(void) | 2217 | int __init tcpv6_init(void) |
2168 | { | 2218 | { |
2169 | int ret; | 2219 | int ret; |
@@ -2177,8 +2227,7 @@ int __init tcpv6_init(void) | |||
2177 | if (ret) | 2227 | if (ret) |
2178 | goto out_tcpv6_protocol; | 2228 | goto out_tcpv6_protocol; |
2179 | 2229 | ||
2180 | ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, | 2230 | ret = register_pernet_subsys(&tcpv6_net_ops); |
2181 | SOCK_RAW, IPPROTO_TCP); | ||
2182 | if (ret) | 2231 | if (ret) |
2183 | goto out_tcpv6_protosw; | 2232 | goto out_tcpv6_protosw; |
2184 | out: | 2233 | out: |
@@ -2193,7 +2242,7 @@ out_tcpv6_protosw: | |||
2193 | 2242 | ||
2194 | void tcpv6_exit(void) | 2243 | void tcpv6_exit(void) |
2195 | { | 2244 | { |
2196 | sock_release(tcp6_socket); | 2245 | unregister_pernet_subsys(&tcpv6_net_ops); |
2197 | inet6_unregister_protosw(&tcpv6_protosw); | 2246 | inet6_unregister_protosw(&tcpv6_protosw); |
2198 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2247 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2199 | } | 2248 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 53739de829db..1fd784f3e2ec 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -51,9 +51,9 @@ | |||
51 | #include <linux/seq_file.h> | 51 | #include <linux/seq_file.h> |
52 | #include "udp_impl.h" | 52 | #include "udp_impl.h" |
53 | 53 | ||
54 | static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) | 54 | int udp_v6_get_port(struct sock *sk, unsigned short snum) |
55 | { | 55 | { |
56 | return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); | 56 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct sock *__udp6_lib_lookup(struct net *net, | 59 | static struct sock *__udp6_lib_lookup(struct net *net, |
@@ -70,7 +70,7 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
70 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 70 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
71 | struct inet_sock *inet = inet_sk(sk); | 71 | struct inet_sock *inet = inet_sk(sk); |
72 | 72 | ||
73 | if (sk->sk_net == net && sk->sk_hash == hnum && | 73 | if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && |
74 | sk->sk_family == PF_INET6) { | 74 | sk->sk_family == PF_INET6) { |
75 | struct ipv6_pinfo *np = inet6_sk(sk); | 75 | struct ipv6_pinfo *np = inet6_sk(sk); |
76 | int score = 0; | 76 | int score = 0; |
@@ -235,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
235 | struct sock *sk; | 235 | struct sock *sk; |
236 | int err; | 236 | int err; |
237 | 237 | ||
238 | sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest, | 238 | sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest, |
239 | saddr, uh->source, inet6_iif(skb), udptable); | 239 | saddr, uh->source, inet6_iif(skb), udptable); |
240 | if (sk == NULL) | 240 | if (sk == NULL) |
241 | return; | 241 | return; |
@@ -323,6 +323,9 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
323 | sk_for_each_from(s, node) { | 323 | sk_for_each_from(s, node) { |
324 | struct inet_sock *inet = inet_sk(s); | 324 | struct inet_sock *inet = inet_sk(s); |
325 | 325 | ||
326 | if (sock_net(s) != sock_net(sk)) | ||
327 | continue; | ||
328 | |||
326 | if (s->sk_hash == num && s->sk_family == PF_INET6) { | 329 | if (s->sk_hash == num && s->sk_family == PF_INET6) { |
327 | struct ipv6_pinfo *np = inet6_sk(s); | 330 | struct ipv6_pinfo *np = inet6_sk(s); |
328 | if (inet->dport) { | 331 | if (inet->dport) { |
@@ -480,7 +483,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
480 | * check socket cache ... must talk to Alan about his plans | 483 | * check socket cache ... must talk to Alan about his plans |
481 | * for sock caches... i'll skip this for now. | 484 | * for sock caches... i'll skip this for now. |
482 | */ | 485 | */ |
483 | sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source, | 486 | sk = __udp6_lib_lookup(dev_net(skb->dev), saddr, uh->source, |
484 | daddr, uh->dest, inet6_iif(skb), udptable); | 487 | daddr, uh->dest, inet6_iif(skb), udptable); |
485 | 488 | ||
486 | if (sk == NULL) { | 489 | if (sk == NULL) { |
@@ -749,7 +752,10 @@ do_udp_sendmsg: | |||
749 | opt = ipv6_fixup_options(&opt_space, opt); | 752 | opt = ipv6_fixup_options(&opt_space, opt); |
750 | 753 | ||
751 | fl.proto = sk->sk_protocol; | 754 | fl.proto = sk->sk_protocol; |
752 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 755 | if (!ipv6_addr_any(daddr)) |
756 | ipv6_addr_copy(&fl.fl6_dst, daddr); | ||
757 | else | ||
758 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
753 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 759 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
754 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 760 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
755 | fl.fl_ip_sport = inet->sport; | 761 | fl.fl_ip_sport = inet->sport; |
@@ -789,9 +795,7 @@ do_udp_sendmsg: | |||
789 | else | 795 | else |
790 | hlimit = np->hop_limit; | 796 | hlimit = np->hop_limit; |
791 | if (hlimit < 0) | 797 | if (hlimit < 0) |
792 | hlimit = dst_metric(dst, RTAX_HOPLIMIT); | 798 | hlimit = ip6_dst_hoplimit(dst); |
793 | if (hlimit < 0) | ||
794 | hlimit = ipv6_get_hoplimit(dst->dev); | ||
795 | } | 799 | } |
796 | 800 | ||
797 | if (tclass < 0) { | 801 | if (tclass < 0) { |
@@ -976,30 +980,30 @@ int udp6_seq_show(struct seq_file *seq, void *v) | |||
976 | return 0; | 980 | return 0; |
977 | } | 981 | } |
978 | 982 | ||
979 | static struct file_operations udp6_seq_fops; | ||
980 | static struct udp_seq_afinfo udp6_seq_afinfo = { | 983 | static struct udp_seq_afinfo udp6_seq_afinfo = { |
981 | .owner = THIS_MODULE, | ||
982 | .name = "udp6", | 984 | .name = "udp6", |
983 | .family = AF_INET6, | 985 | .family = AF_INET6, |
984 | .hashtable = udp_hash, | 986 | .hashtable = udp_hash, |
985 | .seq_show = udp6_seq_show, | 987 | .seq_fops = { |
986 | .seq_fops = &udp6_seq_fops, | 988 | .owner = THIS_MODULE, |
989 | }, | ||
990 | .seq_ops = { | ||
991 | .show = udp6_seq_show, | ||
992 | }, | ||
987 | }; | 993 | }; |
988 | 994 | ||
989 | int __init udp6_proc_init(void) | 995 | int udp6_proc_init(struct net *net) |
990 | { | 996 | { |
991 | return udp_proc_register(&udp6_seq_afinfo); | 997 | return udp_proc_register(net, &udp6_seq_afinfo); |
992 | } | 998 | } |
993 | 999 | ||
994 | void udp6_proc_exit(void) { | 1000 | void udp6_proc_exit(struct net *net) { |
995 | udp_proc_unregister(&udp6_seq_afinfo); | 1001 | udp_proc_unregister(net, &udp6_seq_afinfo); |
996 | } | 1002 | } |
997 | #endif /* CONFIG_PROC_FS */ | 1003 | #endif /* CONFIG_PROC_FS */ |
998 | 1004 | ||
999 | /* ------------------------------------------------------------------------ */ | 1005 | /* ------------------------------------------------------------------------ */ |
1000 | 1006 | ||
1001 | DEFINE_PROTO_INUSE(udpv6) | ||
1002 | |||
1003 | struct proto udpv6_prot = { | 1007 | struct proto udpv6_prot = { |
1004 | .name = "UDPv6", | 1008 | .name = "UDPv6", |
1005 | .owner = THIS_MODULE, | 1009 | .owner = THIS_MODULE, |
@@ -1021,11 +1025,11 @@ struct proto udpv6_prot = { | |||
1021 | .sysctl_wmem = &sysctl_udp_wmem_min, | 1025 | .sysctl_wmem = &sysctl_udp_wmem_min, |
1022 | .sysctl_rmem = &sysctl_udp_rmem_min, | 1026 | .sysctl_rmem = &sysctl_udp_rmem_min, |
1023 | .obj_size = sizeof(struct udp6_sock), | 1027 | .obj_size = sizeof(struct udp6_sock), |
1028 | .h.udp_hash = udp_hash, | ||
1024 | #ifdef CONFIG_COMPAT | 1029 | #ifdef CONFIG_COMPAT |
1025 | .compat_setsockopt = compat_udpv6_setsockopt, | 1030 | .compat_setsockopt = compat_udpv6_setsockopt, |
1026 | .compat_getsockopt = compat_udpv6_getsockopt, | 1031 | .compat_getsockopt = compat_udpv6_getsockopt, |
1027 | #endif | 1032 | #endif |
1028 | REF_PROTO_INUSE(udpv6) | ||
1029 | }; | 1033 | }; |
1030 | 1034 | ||
1031 | static struct inet_protosw udpv6_protosw = { | 1035 | static struct inet_protosw udpv6_protosw = { |
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..491efd00a866 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -35,13 +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) | ||
44 | |||
45 | struct proto udplitev6_prot = { | 38 | struct proto udplitev6_prot = { |
46 | .name = "UDPLITEv6", | 39 | .name = "UDPLITEv6", |
47 | .owner = THIS_MODULE, | 40 | .owner = THIS_MODULE, |
@@ -58,13 +51,13 @@ struct proto udplitev6_prot = { | |||
58 | .backlog_rcv = udpv6_queue_rcv_skb, | 51 | .backlog_rcv = udpv6_queue_rcv_skb, |
59 | .hash = udp_lib_hash, | 52 | .hash = udp_lib_hash, |
60 | .unhash = udp_lib_unhash, | 53 | .unhash = udp_lib_unhash, |
61 | .get_port = udplite_v6_get_port, | 54 | .get_port = udp_v6_get_port, |
62 | .obj_size = sizeof(struct udp6_sock), | 55 | .obj_size = sizeof(struct udp6_sock), |
56 | .h.udp_hash = udplite_hash, | ||
63 | #ifdef CONFIG_COMPAT | 57 | #ifdef CONFIG_COMPAT |
64 | .compat_setsockopt = compat_udpv6_setsockopt, | 58 | .compat_setsockopt = compat_udpv6_setsockopt, |
65 | .compat_getsockopt = compat_udpv6_getsockopt, | 59 | .compat_getsockopt = compat_udpv6_getsockopt, |
66 | #endif | 60 | #endif |
67 | REF_PROTO_INUSE(udplitev6) | ||
68 | }; | 61 | }; |
69 | 62 | ||
70 | static struct inet_protosw udplite6_protosw = { | 63 | static struct inet_protosw udplite6_protosw = { |
@@ -103,23 +96,40 @@ void udplitev6_exit(void) | |||
103 | } | 96 | } |
104 | 97 | ||
105 | #ifdef CONFIG_PROC_FS | 98 | #ifdef CONFIG_PROC_FS |
106 | static struct file_operations udplite6_seq_fops; | ||
107 | static struct udp_seq_afinfo udplite6_seq_afinfo = { | 99 | static struct udp_seq_afinfo udplite6_seq_afinfo = { |
108 | .owner = THIS_MODULE, | ||
109 | .name = "udplite6", | 100 | .name = "udplite6", |
110 | .family = AF_INET6, | 101 | .family = AF_INET6, |
111 | .hashtable = udplite_hash, | 102 | .hashtable = udplite_hash, |
112 | .seq_show = udp6_seq_show, | 103 | .seq_fops = { |
113 | .seq_fops = &udplite6_seq_fops, | 104 | .owner = THIS_MODULE, |
105 | }, | ||
106 | .seq_ops = { | ||
107 | .show = udp6_seq_show, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | static int udplite6_proc_init_net(struct net *net) | ||
112 | { | ||
113 | return udp_proc_register(net, &udplite6_seq_afinfo); | ||
114 | } | ||
115 | |||
116 | static void udplite6_proc_exit_net(struct net *net) | ||
117 | { | ||
118 | udp_proc_unregister(net, &udplite6_seq_afinfo); | ||
119 | } | ||
120 | |||
121 | static struct pernet_operations udplite6_net_ops = { | ||
122 | .init = udplite6_proc_init_net, | ||
123 | .exit = udplite6_proc_exit_net, | ||
114 | }; | 124 | }; |
115 | 125 | ||
116 | int __init udplite6_proc_init(void) | 126 | int __init udplite6_proc_init(void) |
117 | { | 127 | { |
118 | return udp_proc_register(&udplite6_seq_afinfo); | 128 | return register_pernet_subsys(&udplite6_net_ops); |
119 | } | 129 | } |
120 | 130 | ||
121 | void udplite6_proc_exit(void) | 131 | void udplite6_proc_exit(void) |
122 | { | 132 | { |
123 | udp_proc_unregister(&udplite6_seq_afinfo); | 133 | unregister_pernet_subsys(&udplite6_net_ops); |
124 | } | 134 | } |
125 | #endif | 135 | #endif |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index a4714d76ae6b..a71c7ddcb41e 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -59,9 +59,6 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
59 | xfrm_address_t *saddr, u8 proto) | 59 | xfrm_address_t *saddr, u8 proto) |
60 | { | 60 | { |
61 | struct xfrm_state *x = NULL; | 61 | struct xfrm_state *x = NULL; |
62 | int wildcard = 0; | ||
63 | xfrm_address_t *xany; | ||
64 | int nh = 0; | ||
65 | int i = 0; | 62 | int i = 0; |
66 | 63 | ||
67 | /* Allocate new secpath or COW existing one. */ | 64 | /* Allocate new secpath or COW existing one. */ |
@@ -83,10 +80,9 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
83 | goto drop; | 80 | goto drop; |
84 | } | 81 | } |
85 | 82 | ||
86 | xany = (xfrm_address_t *)&in6addr_any; | ||
87 | |||
88 | for (i = 0; i < 3; i++) { | 83 | for (i = 0; i < 3; i++) { |
89 | xfrm_address_t *dst, *src; | 84 | xfrm_address_t *dst, *src; |
85 | |||
90 | switch (i) { | 86 | switch (i) { |
91 | case 0: | 87 | case 0: |
92 | dst = daddr; | 88 | dst = daddr; |
@@ -94,16 +90,13 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
94 | break; | 90 | break; |
95 | case 1: | 91 | case 1: |
96 | /* lookup state with wild-card source address */ | 92 | /* lookup state with wild-card source address */ |
97 | wildcard = 1; | ||
98 | dst = daddr; | 93 | dst = daddr; |
99 | src = xany; | 94 | src = (xfrm_address_t *)&in6addr_any; |
100 | break; | 95 | break; |
101 | case 2: | ||
102 | default: | 96 | default: |
103 | /* lookup state with wild-card addresses */ | 97 | /* lookup state with wild-card addresses */ |
104 | wildcard = 1; /* XXX */ | 98 | dst = (xfrm_address_t *)&in6addr_any; |
105 | dst = xany; | 99 | src = (xfrm_address_t *)&in6addr_any; |
106 | src = xany; | ||
107 | break; | 100 | break; |
108 | } | 101 | } |
109 | 102 | ||
@@ -113,39 +106,19 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
113 | 106 | ||
114 | spin_lock(&x->lock); | 107 | spin_lock(&x->lock); |
115 | 108 | ||
116 | if (wildcard) { | 109 | if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) && |
117 | if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) { | 110 | likely(x->km.state == XFRM_STATE_VALID) && |
118 | spin_unlock(&x->lock); | 111 | !xfrm_state_check_expire(x)) { |
119 | xfrm_state_put(x); | ||
120 | x = NULL; | ||
121 | continue; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { | ||
126 | spin_unlock(&x->lock); | 112 | spin_unlock(&x->lock); |
127 | xfrm_state_put(x); | 113 | if (x->type->input(x, skb) > 0) { |
128 | x = NULL; | 114 | /* found a valid state */ |
129 | continue; | 115 | break; |
130 | } | 116 | } |
131 | if (xfrm_state_check_expire(x)) { | 117 | } else |
132 | spin_unlock(&x->lock); | 118 | spin_unlock(&x->lock); |
133 | xfrm_state_put(x); | ||
134 | x = NULL; | ||
135 | continue; | ||
136 | } | ||
137 | |||
138 | spin_unlock(&x->lock); | ||
139 | |||
140 | nh = x->type->input(x, skb); | ||
141 | if (nh <= 0) { | ||
142 | xfrm_state_put(x); | ||
143 | x = NULL; | ||
144 | continue; | ||
145 | } | ||
146 | 119 | ||
147 | /* Found a state */ | 120 | xfrm_state_put(x); |
148 | break; | 121 | x = NULL; |
149 | } | 122 | } |
150 | 123 | ||
151 | if (!x) { | 124 | if (!x) { |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 7d20199ee1f3..8f1e0543b3c4 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -38,7 +38,7 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr, | |||
38 | if (saddr) | 38 | if (saddr) |
39 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); | 39 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); |
40 | 40 | ||
41 | dst = ip6_route_output(NULL, &fl); | 41 | dst = ip6_route_output(&init_net, NULL, &fl); |
42 | 42 | ||
43 | err = dst->error; | 43 | err = dst->error; |
44 | if (dst->error) { | 44 | if (dst->error) { |
@@ -57,8 +57,9 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) | |||
57 | if (IS_ERR(dst)) | 57 | if (IS_ERR(dst)) |
58 | return -EHOSTUNREACH; | 58 | return -EHOSTUNREACH; |
59 | 59 | ||
60 | ipv6_get_saddr(dst, (struct in6_addr *)&daddr->a6, | 60 | ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev, |
61 | (struct in6_addr *)&saddr->a6); | 61 | (struct in6_addr *)&daddr->a6, 0, |
62 | (struct in6_addr *)&saddr->a6); | ||
62 | dst_release(dst); | 63 | dst_release(dst); |
63 | return 0; | 64 | return 0; |
64 | } | 65 | } |
@@ -246,7 +247,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
246 | xdst = (struct xfrm_dst *)dst; | 247 | xdst = (struct xfrm_dst *)dst; |
247 | if (xdst->u.rt6.rt6i_idev->dev == dev) { | 248 | if (xdst->u.rt6.rt6i_idev->dev == dev) { |
248 | struct inet6_dev *loopback_idev = | 249 | struct inet6_dev *loopback_idev = |
249 | in6_dev_get(dev->nd_net->loopback_dev); | 250 | in6_dev_get(dev_net(dev)->loopback_dev); |
250 | BUG_ON(!loopback_idev); | 251 | BUG_ON(!loopback_idev); |
251 | 252 | ||
252 | do { | 253 | do { |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index ff1e1db8e236..89884a4f23aa 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -49,125 +49,102 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
49 | x->props.family = AF_INET6; | 49 | x->props.family = AF_INET6; |
50 | } | 50 | } |
51 | 51 | ||
52 | /* distribution counting sort function for xfrm_state and xfrm_tmpl */ | ||
52 | static int | 53 | static int |
53 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | 54 | __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass) |
54 | { | 55 | { |
55 | int i; | 56 | int i; |
56 | int j = 0; | 57 | int class[XFRM_MAX_DEPTH]; |
58 | int count[maxclass]; | ||
57 | 59 | ||
58 | /* Rule 1: select IPsec transport except AH */ | 60 | memset(count, 0, sizeof(count)); |
59 | for (i = 0; i < n; i++) { | ||
60 | if (src[i]->props.mode == XFRM_MODE_TRANSPORT && | ||
61 | src[i]->id.proto != IPPROTO_AH) { | ||
62 | dst[j++] = src[i]; | ||
63 | src[i] = NULL; | ||
64 | } | ||
65 | } | ||
66 | if (j == n) | ||
67 | goto end; | ||
68 | 61 | ||
69 | /* Rule 2: select MIPv6 RO or inbound trigger */ | ||
70 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
71 | for (i = 0; i < n; i++) { | 62 | for (i = 0; i < n; i++) { |
72 | if (src[i] && | 63 | int c; |
73 | (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || | 64 | class[i] = c = cmp(src[i]); |
74 | src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) { | 65 | count[c]++; |
75 | dst[j++] = src[i]; | ||
76 | src[i] = NULL; | ||
77 | } | ||
78 | } | 66 | } |
79 | if (j == n) | ||
80 | goto end; | ||
81 | #endif | ||
82 | 67 | ||
83 | /* Rule 3: select IPsec transport AH */ | 68 | for (i = 2; i < maxclass; i++) |
84 | for (i = 0; i < n; i++) { | 69 | count[i] += count[i - 1]; |
85 | if (src[i] && | ||
86 | src[i]->props.mode == XFRM_MODE_TRANSPORT && | ||
87 | src[i]->id.proto == IPPROTO_AH) { | ||
88 | dst[j++] = src[i]; | ||
89 | src[i] = NULL; | ||
90 | } | ||
91 | } | ||
92 | if (j == n) | ||
93 | goto end; | ||
94 | 70 | ||
95 | /* Rule 4: select IPsec tunnel */ | ||
96 | for (i = 0; i < n; i++) { | 71 | for (i = 0; i < n; i++) { |
97 | if (src[i] && | 72 | dst[count[class[i] - 1]++] = src[i]; |
98 | (src[i]->props.mode == XFRM_MODE_TUNNEL || | 73 | src[i] = 0; |
99 | src[i]->props.mode == XFRM_MODE_BEET)) { | ||
100 | dst[j++] = src[i]; | ||
101 | src[i] = NULL; | ||
102 | } | ||
103 | } | 74 | } |
104 | if (likely(j == n)) | ||
105 | goto end; | ||
106 | 75 | ||
107 | /* Final rule */ | ||
108 | for (i = 0; i < n; i++) { | ||
109 | if (src[i]) { | ||
110 | dst[j++] = src[i]; | ||
111 | src[i] = NULL; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | end: | ||
116 | return 0; | 76 | return 0; |
117 | } | 77 | } |
118 | 78 | ||
119 | static int | 79 | /* |
120 | __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | 80 | * Rule for xfrm_state: |
81 | * | ||
82 | * rule 1: select IPsec transport except AH | ||
83 | * rule 2: select MIPv6 RO or inbound trigger | ||
84 | * rule 3: select IPsec transport AH | ||
85 | * rule 4: select IPsec tunnel | ||
86 | * rule 5: others | ||
87 | */ | ||
88 | static int __xfrm6_state_sort_cmp(void *p) | ||
121 | { | 89 | { |
122 | int i; | 90 | struct xfrm_state *v = p; |
123 | int j = 0; | 91 | |
124 | 92 | switch (v->props.mode) { | |
125 | /* Rule 1: select IPsec transport */ | 93 | case XFRM_MODE_TRANSPORT: |
126 | for (i = 0; i < n; i++) { | 94 | if (v->id.proto != IPPROTO_AH) |
127 | if (src[i]->mode == XFRM_MODE_TRANSPORT) { | 95 | return 1; |
128 | dst[j++] = src[i]; | 96 | else |
129 | src[i] = NULL; | 97 | return 3; |
130 | } | ||
131 | } | ||
132 | if (j == n) | ||
133 | goto end; | ||
134 | |||
135 | /* Rule 2: select MIPv6 RO or inbound trigger */ | ||
136 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 98 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
137 | for (i = 0; i < n; i++) { | 99 | case XFRM_MODE_ROUTEOPTIMIZATION: |
138 | if (src[i] && | 100 | case XFRM_MODE_IN_TRIGGER: |
139 | (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || | 101 | return 2; |
140 | src[i]->mode == XFRM_MODE_IN_TRIGGER)) { | ||
141 | dst[j++] = src[i]; | ||
142 | src[i] = NULL; | ||
143 | } | ||
144 | } | ||
145 | if (j == n) | ||
146 | goto end; | ||
147 | #endif | 102 | #endif |
148 | 103 | case XFRM_MODE_TUNNEL: | |
149 | /* Rule 3: select IPsec tunnel */ | 104 | case XFRM_MODE_BEET: |
150 | for (i = 0; i < n; i++) { | 105 | return 4; |
151 | if (src[i] && | ||
152 | (src[i]->mode == XFRM_MODE_TUNNEL || | ||
153 | src[i]->mode == XFRM_MODE_BEET)) { | ||
154 | dst[j++] = src[i]; | ||
155 | src[i] = NULL; | ||
156 | } | ||
157 | } | 106 | } |
158 | if (likely(j == n)) | 107 | return 5; |
159 | goto end; | 108 | } |
160 | 109 | ||
161 | /* Final rule */ | 110 | static int |
162 | for (i = 0; i < n; i++) { | 111 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) |
163 | if (src[i]) { | 112 | { |
164 | dst[j++] = src[i]; | 113 | return __xfrm6_sort((void **)dst, (void **)src, n, |
165 | src[i] = NULL; | 114 | __xfrm6_state_sort_cmp, 6); |
166 | } | 115 | } |
116 | |||
117 | /* | ||
118 | * Rule for xfrm_tmpl: | ||
119 | * | ||
120 | * rule 1: select IPsec transport | ||
121 | * rule 2: select MIPv6 RO or inbound trigger | ||
122 | * rule 3: select IPsec tunnel | ||
123 | * rule 4: others | ||
124 | */ | ||
125 | static int __xfrm6_tmpl_sort_cmp(void *p) | ||
126 | { | ||
127 | struct xfrm_tmpl *v = p; | ||
128 | switch (v->mode) { | ||
129 | case XFRM_MODE_TRANSPORT: | ||
130 | return 1; | ||
131 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
132 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
133 | case XFRM_MODE_IN_TRIGGER: | ||
134 | return 2; | ||
135 | #endif | ||
136 | case XFRM_MODE_TUNNEL: | ||
137 | case XFRM_MODE_BEET: | ||
138 | return 3; | ||
167 | } | 139 | } |
140 | return 4; | ||
141 | } | ||
168 | 142 | ||
169 | end: | 143 | static int |
170 | return 0; | 144 | __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) |
145 | { | ||
146 | return __xfrm6_sort((void **)dst, (void **)src, n, | ||
147 | __xfrm6_tmpl_sort_cmp, 5); | ||
171 | } | 148 | } |
172 | 149 | ||
173 | int xfrm6_extract_header(struct sk_buff *skb) | 150 | int xfrm6_extract_header(struct sk_buff *skb) |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 639fe8a6ff1e..c2b278138604 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -140,12 +140,26 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) | |||
140 | 140 | ||
141 | EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); | 141 | EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); |
142 | 142 | ||
143 | static int __xfrm6_tunnel_spi_check(u32 spi) | ||
144 | { | ||
145 | struct xfrm6_tunnel_spi *x6spi; | ||
146 | int index = xfrm6_tunnel_spi_hash_byspi(spi); | ||
147 | struct hlist_node *pos; | ||
148 | |||
149 | hlist_for_each_entry(x6spi, pos, | ||
150 | &xfrm6_tunnel_spi_byspi[index], | ||
151 | list_byspi) { | ||
152 | if (x6spi->spi == spi) | ||
153 | return -1; | ||
154 | } | ||
155 | return index; | ||
156 | } | ||
157 | |||
143 | static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) | 158 | static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) |
144 | { | 159 | { |
145 | u32 spi; | 160 | u32 spi; |
146 | struct xfrm6_tunnel_spi *x6spi; | 161 | struct xfrm6_tunnel_spi *x6spi; |
147 | struct hlist_node *pos; | 162 | int index; |
148 | unsigned index; | ||
149 | 163 | ||
150 | if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || | 164 | if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || |
151 | xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) | 165 | xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) |
@@ -154,32 +168,19 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) | |||
154 | xfrm6_tunnel_spi++; | 168 | xfrm6_tunnel_spi++; |
155 | 169 | ||
156 | for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { | 170 | for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { |
157 | index = xfrm6_tunnel_spi_hash_byspi(spi); | 171 | index = __xfrm6_tunnel_spi_check(spi); |
158 | hlist_for_each_entry(x6spi, pos, | 172 | if (index >= 0) |
159 | &xfrm6_tunnel_spi_byspi[index], | 173 | goto alloc_spi; |
160 | list_byspi) { | ||
161 | if (x6spi->spi == spi) | ||
162 | goto try_next_1; | ||
163 | } | ||
164 | xfrm6_tunnel_spi = spi; | ||
165 | goto alloc_spi; | ||
166 | try_next_1:; | ||
167 | } | 174 | } |
168 | for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { | 175 | for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { |
169 | index = xfrm6_tunnel_spi_hash_byspi(spi); | 176 | index = __xfrm6_tunnel_spi_check(spi); |
170 | hlist_for_each_entry(x6spi, pos, | 177 | if (index >= 0) |
171 | &xfrm6_tunnel_spi_byspi[index], | 178 | goto alloc_spi; |
172 | list_byspi) { | ||
173 | if (x6spi->spi == spi) | ||
174 | goto try_next_2; | ||
175 | } | ||
176 | xfrm6_tunnel_spi = spi; | ||
177 | goto alloc_spi; | ||
178 | try_next_2:; | ||
179 | } | 179 | } |
180 | spi = 0; | 180 | spi = 0; |
181 | goto out; | 181 | goto out; |
182 | alloc_spi: | 182 | alloc_spi: |
183 | xfrm6_tunnel_spi = spi; | ||
183 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); | 184 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); |
184 | if (!x6spi) | 185 | if (!x6spi) |
185 | goto out; | 186 | goto out; |