diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/Kconfig | 18 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 116 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 60 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 4 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 3 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 22 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 38 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 137 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_HL.c | 95 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_hl.c | 68 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_security.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 10 | ||||
-rw-r--r-- | net/ipv6/route.c | 9 | ||||
-rw-r--r-- | net/ipv6/sit.c | 5 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 8 | ||||
-rw-r--r-- | net/ipv6/udp.c | 28 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 2 |
25 files changed, 268 insertions, 373 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index ec992159b5f8..ca8cb326d1d2 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -22,17 +22,17 @@ menuconfig IPV6 | |||
22 | if IPV6 | 22 | if IPV6 |
23 | 23 | ||
24 | config IPV6_PRIVACY | 24 | config IPV6_PRIVACY |
25 | bool "IPv6: Privacy Extensions support" | 25 | bool "IPv6: Privacy Extensions (RFC 3041) support" |
26 | ---help--- | 26 | ---help--- |
27 | Privacy Extensions for Stateless Address Autoconfiguration in IPv6 | 27 | Privacy Extensions for Stateless Address Autoconfiguration in IPv6 |
28 | support. With this option, additional periodically-alter | 28 | support. With this option, additional periodically-altered |
29 | pseudo-random global-scope unicast address(es) will assigned to | 29 | pseudo-random global-scope unicast address(es) will be assigned to |
30 | your interface(s). | 30 | your interface(s). |
31 | 31 | ||
32 | We use our standard pseudo random algorithm to generate randomized | 32 | We use our standard pseudo-random algorithm to generate the |
33 | interface identifier, instead of one described in RFC 3041. | 33 | randomized interface identifier, instead of one described in RFC 3041. |
34 | 34 | ||
35 | By default, kernel do not generate temporary addresses. | 35 | By default the kernel does not generate temporary addresses. |
36 | To use temporary addresses, do | 36 | To use temporary addresses, do |
37 | 37 | ||
38 | echo 2 >/proc/sys/net/ipv6/conf/all/use_tempaddr | 38 | echo 2 >/proc/sys/net/ipv6/conf/all/use_tempaddr |
@@ -43,9 +43,9 @@ config IPV6_ROUTER_PREF | |||
43 | bool "IPv6: Router Preference (RFC 4191) support" | 43 | bool "IPv6: Router Preference (RFC 4191) support" |
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 which improves the ability of hosts |
47 | to pick more appropriate router, especially when the hosts | 47 | to pick an appropriate router, especially when the hosts |
48 | is placed in a multi-homed network. | 48 | are placed in a multi-homed network. |
49 | 49 | ||
50 | If unsure, say N. | 50 | If unsure, say N. |
51 | 51 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1220e2c7831e..a8218bc1806a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -40,6 +40,7 @@ | |||
40 | 40 | ||
41 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
42 | #include <linux/types.h> | 42 | #include <linux/types.h> |
43 | #include <linux/kernel.h> | ||
43 | #include <linux/socket.h> | 44 | #include <linux/socket.h> |
44 | #include <linux/sockios.h> | 45 | #include <linux/sockios.h> |
45 | #include <linux/net.h> | 46 | #include <linux/net.h> |
@@ -590,6 +591,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
590 | { | 591 | { |
591 | struct inet6_ifaddr *ifa = NULL; | 592 | struct inet6_ifaddr *ifa = NULL; |
592 | struct rt6_info *rt; | 593 | struct rt6_info *rt; |
594 | struct net *net = dev_net(idev->dev); | ||
593 | int hash; | 595 | int hash; |
594 | int err = 0; | 596 | int err = 0; |
595 | int addr_type = ipv6_addr_type(addr); | 597 | int addr_type = ipv6_addr_type(addr); |
@@ -606,6 +608,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
606 | goto out2; | 608 | goto out2; |
607 | } | 609 | } |
608 | 610 | ||
611 | if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) { | ||
612 | err = -EACCES; | ||
613 | goto out2; | ||
614 | } | ||
615 | |||
609 | write_lock(&addrconf_hash_lock); | 616 | write_lock(&addrconf_hash_lock); |
610 | 617 | ||
611 | /* Ignore adding duplicate addresses on an interface */ | 618 | /* Ignore adding duplicate addresses on an interface */ |
@@ -1209,16 +1216,12 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1209 | } | 1216 | } |
1210 | break; | 1217 | break; |
1211 | } else if (minihiscore < miniscore) { | 1218 | } else if (minihiscore < miniscore) { |
1212 | struct ipv6_saddr_score *tmp; | ||
1213 | |||
1214 | if (hiscore->ifa) | 1219 | if (hiscore->ifa) |
1215 | in6_ifa_put(hiscore->ifa); | 1220 | in6_ifa_put(hiscore->ifa); |
1216 | 1221 | ||
1217 | in6_ifa_hold(score->ifa); | 1222 | in6_ifa_hold(score->ifa); |
1218 | 1223 | ||
1219 | tmp = hiscore; | 1224 | swap(hiscore, score); |
1220 | hiscore = score; | ||
1221 | score = tmp; | ||
1222 | 1225 | ||
1223 | /* restore our iterator */ | 1226 | /* restore our iterator */ |
1224 | score->ifa = hiscore->ifa; | 1227 | score->ifa = hiscore->ifa; |
@@ -1367,40 +1370,6 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add | |||
1367 | return ifp; | 1370 | return ifp; |
1368 | } | 1371 | } |
1369 | 1372 | ||
1370 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | ||
1371 | { | ||
1372 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; | ||
1373 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | ||
1374 | __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr; | ||
1375 | __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); | ||
1376 | int sk_ipv6only = ipv6_only_sock(sk); | ||
1377 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | ||
1378 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); | ||
1379 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | ||
1380 | |||
1381 | if (!sk2_rcv_saddr && !sk_ipv6only) | ||
1382 | return 1; | ||
1383 | |||
1384 | if (addr_type2 == IPV6_ADDR_ANY && | ||
1385 | !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) | ||
1386 | return 1; | ||
1387 | |||
1388 | if (addr_type == IPV6_ADDR_ANY && | ||
1389 | !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) | ||
1390 | return 1; | ||
1391 | |||
1392 | if (sk2_rcv_saddr6 && | ||
1393 | ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6)) | ||
1394 | return 1; | ||
1395 | |||
1396 | if (addr_type == IPV6_ADDR_MAPPED && | ||
1397 | !sk2_ipv6only && | ||
1398 | (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr)) | ||
1399 | return 1; | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | /* Gets referenced address, destroys ifaddr */ | 1373 | /* Gets referenced address, destroys ifaddr */ |
1405 | 1374 | ||
1406 | static void addrconf_dad_stop(struct inet6_ifaddr *ifp) | 1375 | static void addrconf_dad_stop(struct inet6_ifaddr *ifp) |
@@ -1433,6 +1402,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp) | |||
1433 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1402 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
1434 | { | 1403 | { |
1435 | struct inet6_dev *idev = ifp->idev; | 1404 | struct inet6_dev *idev = ifp->idev; |
1405 | |||
1406 | if (net_ratelimit()) | ||
1407 | printk(KERN_INFO "%s: IPv6 duplicate address detected!\n", | ||
1408 | ifp->idev->dev->name); | ||
1409 | |||
1436 | if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { | 1410 | if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { |
1437 | struct in6_addr addr; | 1411 | struct in6_addr addr; |
1438 | 1412 | ||
@@ -1443,11 +1417,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1443 | ipv6_addr_equal(&ifp->addr, &addr)) { | 1417 | ipv6_addr_equal(&ifp->addr, &addr)) { |
1444 | /* DAD failed for link-local based on MAC address */ | 1418 | /* DAD failed for link-local based on MAC address */ |
1445 | idev->cnf.disable_ipv6 = 1; | 1419 | idev->cnf.disable_ipv6 = 1; |
1420 | |||
1421 | printk(KERN_INFO "%s: IPv6 being disabled!\n", | ||
1422 | ifp->idev->dev->name); | ||
1446 | } | 1423 | } |
1447 | } | 1424 | } |
1448 | 1425 | ||
1449 | if (net_ratelimit()) | ||
1450 | printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); | ||
1451 | addrconf_dad_stop(ifp); | 1426 | addrconf_dad_stop(ifp); |
1452 | } | 1427 | } |
1453 | 1428 | ||
@@ -2227,10 +2202,24 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg) | |||
2227 | return err; | 2202 | return err; |
2228 | } | 2203 | } |
2229 | 2204 | ||
2205 | static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | ||
2206 | int plen, int scope) | ||
2207 | { | ||
2208 | struct inet6_ifaddr *ifp; | ||
2209 | |||
2210 | ifp = ipv6_add_addr(idev, addr, plen, scope, IFA_F_PERMANENT); | ||
2211 | if (!IS_ERR(ifp)) { | ||
2212 | spin_lock_bh(&ifp->lock); | ||
2213 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2214 | spin_unlock_bh(&ifp->lock); | ||
2215 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2216 | in6_ifa_put(ifp); | ||
2217 | } | ||
2218 | } | ||
2219 | |||
2230 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2220 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
2231 | static void sit_add_v4_addrs(struct inet6_dev *idev) | 2221 | static void sit_add_v4_addrs(struct inet6_dev *idev) |
2232 | { | 2222 | { |
2233 | struct inet6_ifaddr * ifp; | ||
2234 | struct in6_addr addr; | 2223 | struct in6_addr addr; |
2235 | struct net_device *dev; | 2224 | struct net_device *dev; |
2236 | struct net *net = dev_net(idev->dev); | 2225 | struct net *net = dev_net(idev->dev); |
@@ -2249,14 +2238,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2249 | } | 2238 | } |
2250 | 2239 | ||
2251 | if (addr.s6_addr32[3]) { | 2240 | if (addr.s6_addr32[3]) { |
2252 | ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT); | 2241 | add_addr(idev, &addr, 128, scope); |
2253 | if (!IS_ERR(ifp)) { | ||
2254 | spin_lock_bh(&ifp->lock); | ||
2255 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2256 | spin_unlock_bh(&ifp->lock); | ||
2257 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2258 | in6_ifa_put(ifp); | ||
2259 | } | ||
2260 | return; | 2242 | return; |
2261 | } | 2243 | } |
2262 | 2244 | ||
@@ -2284,15 +2266,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2284 | else | 2266 | else |
2285 | plen = 96; | 2267 | plen = 96; |
2286 | 2268 | ||
2287 | ifp = ipv6_add_addr(idev, &addr, plen, flag, | 2269 | add_addr(idev, &addr, plen, flag); |
2288 | IFA_F_PERMANENT); | ||
2289 | if (!IS_ERR(ifp)) { | ||
2290 | spin_lock_bh(&ifp->lock); | ||
2291 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2292 | spin_unlock_bh(&ifp->lock); | ||
2293 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2294 | in6_ifa_put(ifp); | ||
2295 | } | ||
2296 | } | 2270 | } |
2297 | } | 2271 | } |
2298 | } | 2272 | } |
@@ -2302,7 +2276,6 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2302 | static void init_loopback(struct net_device *dev) | 2276 | static void init_loopback(struct net_device *dev) |
2303 | { | 2277 | { |
2304 | struct inet6_dev *idev; | 2278 | struct inet6_dev *idev; |
2305 | struct inet6_ifaddr * ifp; | ||
2306 | 2279 | ||
2307 | /* ::1 */ | 2280 | /* ::1 */ |
2308 | 2281 | ||
@@ -2313,14 +2286,7 @@ static void init_loopback(struct net_device *dev) | |||
2313 | return; | 2286 | return; |
2314 | } | 2287 | } |
2315 | 2288 | ||
2316 | ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT); | 2289 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
2317 | if (!IS_ERR(ifp)) { | ||
2318 | spin_lock_bh(&ifp->lock); | ||
2319 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2320 | spin_unlock_bh(&ifp->lock); | ||
2321 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2322 | in6_ifa_put(ifp); | ||
2323 | } | ||
2324 | } | 2290 | } |
2325 | 2291 | ||
2326 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) | 2292 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) |
@@ -2832,11 +2798,6 @@ static void addrconf_dad_timer(unsigned long data) | |||
2832 | read_unlock_bh(&idev->lock); | 2798 | read_unlock_bh(&idev->lock); |
2833 | goto out; | 2799 | goto out; |
2834 | } | 2800 | } |
2835 | if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) { | ||
2836 | read_unlock_bh(&idev->lock); | ||
2837 | addrconf_dad_failure(ifp); | ||
2838 | return; | ||
2839 | } | ||
2840 | spin_lock_bh(&ifp->lock); | 2801 | spin_lock_bh(&ifp->lock); |
2841 | if (ifp->probes == 0) { | 2802 | if (ifp->probes == 0) { |
2842 | /* | 2803 | /* |
@@ -3647,7 +3608,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3647 | kfree_skb(skb); | 3608 | kfree_skb(skb); |
3648 | goto errout; | 3609 | goto errout; |
3649 | } | 3610 | } |
3650 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3611 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3612 | return; | ||
3651 | errout: | 3613 | errout: |
3652 | if (err < 0) | 3614 | if (err < 0) |
3653 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); | 3615 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
@@ -3858,7 +3820,8 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3858 | kfree_skb(skb); | 3820 | kfree_skb(skb); |
3859 | goto errout; | 3821 | goto errout; |
3860 | } | 3822 | } |
3861 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3823 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3824 | return; | ||
3862 | errout: | 3825 | errout: |
3863 | if (err < 0) | 3826 | if (err < 0) |
3864 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); | 3827 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
@@ -3928,7 +3891,8 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3928 | kfree_skb(skb); | 3891 | kfree_skb(skb); |
3929 | goto errout; | 3892 | goto errout; |
3930 | } | 3893 | } |
3931 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3894 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3895 | return; | ||
3932 | errout: | 3896 | errout: |
3933 | if (err < 0) | 3897 | if (err < 0) |
3934 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); | 3898 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 9c8309ed35cf..61f55386a236 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -276,11 +276,26 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
276 | 276 | ||
277 | /* Check if the address belongs to the host. */ | 277 | /* Check if the address belongs to the host. */ |
278 | if (addr_type == IPV6_ADDR_MAPPED) { | 278 | if (addr_type == IPV6_ADDR_MAPPED) { |
279 | v4addr = addr->sin6_addr.s6_addr32[3]; | 279 | int chk_addr_ret; |
280 | if (inet_addr_type(net, v4addr) != RTN_LOCAL) { | 280 | |
281 | err = -EADDRNOTAVAIL; | 281 | /* Binding to v4-mapped address on a v6-only socket |
282 | * makes no sense | ||
283 | */ | ||
284 | if (np->ipv6only) { | ||
285 | err = -EINVAL; | ||
282 | goto out; | 286 | goto out; |
283 | } | 287 | } |
288 | |||
289 | /* Reproduce AF_INET checks to make the bindings consitant */ | ||
290 | v4addr = addr->sin6_addr.s6_addr32[3]; | ||
291 | chk_addr_ret = inet_addr_type(net, v4addr); | ||
292 | if (!sysctl_ip_nonlocal_bind && | ||
293 | !(inet->freebind || inet->transparent) && | ||
294 | v4addr != htonl(INADDR_ANY) && | ||
295 | chk_addr_ret != RTN_LOCAL && | ||
296 | chk_addr_ret != RTN_MULTICAST && | ||
297 | chk_addr_ret != RTN_BROADCAST) | ||
298 | goto out; | ||
284 | } else { | 299 | } else { |
285 | if (addr_type != IPV6_ADDR_ANY) { | 300 | if (addr_type != IPV6_ADDR_ANY) { |
286 | struct net_device *dev = NULL; | 301 | struct net_device *dev = NULL; |
@@ -339,8 +354,11 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
339 | goto out; | 354 | goto out; |
340 | } | 355 | } |
341 | 356 | ||
342 | if (addr_type != IPV6_ADDR_ANY) | 357 | if (addr_type != IPV6_ADDR_ANY) { |
343 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; | 358 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; |
359 | if (addr_type != IPV6_ADDR_MAPPED) | ||
360 | np->ipv6only = 1; | ||
361 | } | ||
344 | if (snum) | 362 | if (snum) |
345 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 363 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; |
346 | inet->sport = htons(inet->num); | 364 | inet->sport = htons(inet->num); |
@@ -803,24 +821,34 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
803 | int proto; | 821 | int proto; |
804 | __wsum csum; | 822 | __wsum csum; |
805 | 823 | ||
806 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | 824 | iph = skb_gro_header(skb, sizeof(*iph)); |
825 | if (unlikely(!iph)) | ||
807 | goto out; | 826 | goto out; |
808 | 827 | ||
809 | iph = ipv6_hdr(skb); | 828 | skb_gro_pull(skb, sizeof(*iph)); |
810 | __skb_pull(skb, sizeof(*iph)); | 829 | skb_set_transport_header(skb, skb_gro_offset(skb)); |
811 | 830 | ||
812 | flush += ntohs(iph->payload_len) != skb->len; | 831 | flush += ntohs(iph->payload_len) != skb_gro_len(skb); |
813 | 832 | ||
814 | rcu_read_lock(); | 833 | rcu_read_lock(); |
815 | proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr); | 834 | proto = iph->nexthdr; |
816 | iph = ipv6_hdr(skb); | ||
817 | IPV6_GRO_CB(skb)->proto = proto; | ||
818 | ops = rcu_dereference(inet6_protos[proto]); | 835 | ops = rcu_dereference(inet6_protos[proto]); |
819 | if (!ops || !ops->gro_receive) | 836 | if (!ops || !ops->gro_receive) { |
820 | goto out_unlock; | 837 | __pskb_pull(skb, skb_gro_offset(skb)); |
838 | proto = ipv6_gso_pull_exthdrs(skb, proto); | ||
839 | skb_gro_pull(skb, -skb_transport_offset(skb)); | ||
840 | skb_reset_transport_header(skb); | ||
841 | __skb_push(skb, skb_gro_offset(skb)); | ||
842 | |||
843 | if (!ops || !ops->gro_receive) | ||
844 | goto out_unlock; | ||
845 | |||
846 | iph = ipv6_hdr(skb); | ||
847 | } | ||
848 | |||
849 | IPV6_GRO_CB(skb)->proto = proto; | ||
821 | 850 | ||
822 | flush--; | 851 | flush--; |
823 | skb_reset_transport_header(skb); | ||
824 | nlen = skb_network_header_len(skb); | 852 | nlen = skb_network_header_len(skb); |
825 | 853 | ||
826 | for (p = *head; p; p = p->next) { | 854 | for (p = *head; p; p = p->next) { |
@@ -883,8 +911,8 @@ out_unlock: | |||
883 | return err; | 911 | return err; |
884 | } | 912 | } |
885 | 913 | ||
886 | static struct packet_type ipv6_packet_type = { | 914 | static struct packet_type ipv6_packet_type __read_mostly = { |
887 | .type = __constant_htons(ETH_P_IPV6), | 915 | .type = cpu_to_be16(ETH_P_IPV6), |
888 | .func = ipv6_rcv, | 916 | .func = ipv6_rcv, |
889 | .gso_send_check = ipv6_gso_send_check, | 917 | .gso_send_check = ipv6_gso_send_check, |
890 | .gso_segment = ipv6_gso_segment, | 918 | .gso_segment = ipv6_gso_segment, |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index f171e8dbac91..8f04bd9da274 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -75,8 +75,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
75 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || | 75 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || |
76 | !idev || unlikely(idev->cnf.disable_ipv6)) { | 76 | !idev || unlikely(idev->cnf.disable_ipv6)) { |
77 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS); | 77 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS); |
78 | rcu_read_unlock(); | 78 | goto drop; |
79 | goto out; | ||
80 | } | 79 | } |
81 | 80 | ||
82 | memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); | 81 | memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); |
@@ -147,7 +146,6 @@ err: | |||
147 | drop: | 146 | drop: |
148 | rcu_read_unlock(); | 147 | rcu_read_unlock(); |
149 | kfree_skb(skb); | 148 | kfree_skb(skb); |
150 | out: | ||
151 | return 0; | 149 | return 0; |
152 | } | 150 | } |
153 | 151 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 40f324655e24..d31df0f4bc9a 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -218,8 +218,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
218 | if (opt) | 218 | if (opt) |
219 | sock_kfree_s(sk, opt, opt->tot_len); | 219 | sock_kfree_s(sk, opt, opt->tot_len); |
220 | pktopt = xchg(&np->pktoptions, NULL); | 220 | pktopt = xchg(&np->pktoptions, NULL); |
221 | if (pktopt) | 221 | kfree_skb(pktopt); |
222 | kfree_skb(pktopt); | ||
223 | 222 | ||
224 | sk->sk_destruct = inet_sock_destruct; | 223 | sk->sk_destruct = inet_sock_destruct; |
225 | /* | 224 | /* |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3e2970841bd8..9f061d1adbc2 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1095,11 +1095,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1095 | &ipv6_hdr(ra)->saddr); | 1095 | &ipv6_hdr(ra)->saddr); |
1096 | nlmsg_end(skb, nlh); | 1096 | nlmsg_end(skb, nlh); |
1097 | 1097 | ||
1098 | err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, | 1098 | rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC); |
1099 | GFP_ATOMIC); | ||
1100 | if (err < 0) | ||
1101 | goto errout; | ||
1102 | |||
1103 | return; | 1099 | return; |
1104 | 1100 | ||
1105 | nla_put_failure: | 1101 | nla_put_failure: |
@@ -1538,13 +1534,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1538 | if (rt->rt6i_flags & RTF_GATEWAY) { | 1534 | if (rt->rt6i_flags & RTF_GATEWAY) { |
1539 | ND_PRINTK2(KERN_WARNING | 1535 | ND_PRINTK2(KERN_WARNING |
1540 | "ICMPv6 Redirect: destination is not a neighbour.\n"); | 1536 | "ICMPv6 Redirect: destination is not a neighbour.\n"); |
1541 | dst_release(dst); | 1537 | goto release; |
1542 | return; | ||
1543 | } | ||
1544 | if (!xrlim_allow(dst, 1*HZ)) { | ||
1545 | dst_release(dst); | ||
1546 | return; | ||
1547 | } | 1538 | } |
1539 | if (!xrlim_allow(dst, 1*HZ)) | ||
1540 | goto release; | ||
1548 | 1541 | ||
1549 | if (dev->addr_len) { | 1542 | if (dev->addr_len) { |
1550 | read_lock_bh(&neigh->lock); | 1543 | read_lock_bh(&neigh->lock); |
@@ -1570,8 +1563,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1570 | ND_PRINTK0(KERN_ERR | 1563 | ND_PRINTK0(KERN_ERR |
1571 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", | 1564 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", |
1572 | __func__); | 1565 | __func__); |
1573 | dst_release(dst); | 1566 | goto release; |
1574 | return; | ||
1575 | } | 1567 | } |
1576 | 1568 | ||
1577 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1569 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); |
@@ -1631,6 +1623,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1631 | 1623 | ||
1632 | if (likely(idev != NULL)) | 1624 | if (likely(idev != NULL)) |
1633 | in6_dev_put(idev); | 1625 | in6_dev_put(idev); |
1626 | return; | ||
1627 | |||
1628 | release: | ||
1629 | dst_release(dst); | ||
1634 | } | 1630 | } |
1635 | 1631 | ||
1636 | static void pndisc_redo(struct sk_buff *skb) | 1632 | static void pndisc_redo(struct sk_buff *skb) |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 53ea512c4608..29d643bcafa4 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -95,13 +95,13 @@ config IP6_NF_MATCH_OPTS | |||
95 | To compile it as a module, choose M here. If unsure, say N. | 95 | To compile it as a module, choose M here. If unsure, say N. |
96 | 96 | ||
97 | config IP6_NF_MATCH_HL | 97 | config IP6_NF_MATCH_HL |
98 | tristate '"hl" match support' | 98 | tristate '"hl" hoplimit match support' |
99 | depends on NETFILTER_ADVANCED | 99 | depends on NETFILTER_ADVANCED |
100 | help | 100 | select NETFILTER_XT_MATCH_HL |
101 | HL matching allows you to match packets based on the hop | 101 | ---help--- |
102 | limit of the packet. | 102 | This is a backwards-compat option for the user's convenience |
103 | 103 | (e.g. when running oldconfig). It selects | |
104 | To compile it as a module, choose M here. If unsure, say N. | 104 | CONFIG_NETFILTER_XT_MATCH_HL. |
105 | 105 | ||
106 | config IP6_NF_MATCH_IPV6HEADER | 106 | config IP6_NF_MATCH_IPV6HEADER |
107 | tristate '"ipv6header" IPv6 Extension Headers Match' | 107 | tristate '"ipv6header" IPv6 Extension Headers Match' |
@@ -130,6 +130,15 @@ config IP6_NF_MATCH_RT | |||
130 | To compile it as a module, choose M here. If unsure, say N. | 130 | To compile it as a module, choose M here. If unsure, say N. |
131 | 131 | ||
132 | # The targets | 132 | # The targets |
133 | config IP6_NF_TARGET_HL | ||
134 | tristate '"HL" hoplimit target support' | ||
135 | depends on NETFILTER_ADVANCED | ||
136 | select NETFILTER_XT_TARGET_HL | ||
137 | ---help--- | ||
138 | This is a backwards-compat option for the user's convenience | ||
139 | (e.g. when running oldconfig). It selects | ||
140 | CONFIG_NETFILTER_XT_TARGET_HL. | ||
141 | |||
133 | config IP6_NF_TARGET_LOG | 142 | config IP6_NF_TARGET_LOG |
134 | tristate "LOG target support" | 143 | tristate "LOG target support" |
135 | default m if NETFILTER_ADVANCED=n | 144 | default m if NETFILTER_ADVANCED=n |
@@ -170,23 +179,6 @@ config IP6_NF_MANGLE | |||
170 | 179 | ||
171 | To compile it as a module, choose M here. If unsure, say N. | 180 | To compile it as a module, choose M here. If unsure, say N. |
172 | 181 | ||
173 | config IP6_NF_TARGET_HL | ||
174 | tristate 'HL (hoplimit) target support' | ||
175 | depends on IP6_NF_MANGLE | ||
176 | depends on NETFILTER_ADVANCED | ||
177 | help | ||
178 | This option adds a `HL' target, which enables the user to decrement | ||
179 | the hoplimit value of the IPv6 header or set it to a given (lower) | ||
180 | value. | ||
181 | |||
182 | While it is safe to decrement the hoplimit value, this option also | ||
183 | enables functionality to increment and set the hoplimit value of the | ||
184 | IPv6 header to arbitrary values. This is EXTREMELY DANGEROUS since | ||
185 | you can easily create immortal packets that loop forever on the | ||
186 | network. | ||
187 | |||
188 | To compile it as a module, choose M here. If unsure, say N. | ||
189 | |||
190 | config IP6_NF_RAW | 182 | config IP6_NF_RAW |
191 | tristate 'raw table support (required for TRACE)' | 183 | tristate 'raw table support (required for TRACE)' |
192 | depends on NETFILTER_ADVANCED | 184 | depends on NETFILTER_ADVANCED |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 3f17c948eefb..aafbba30c899 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -20,13 +20,11 @@ obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o | |||
20 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 20 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
21 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o | 21 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o |
22 | obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o | 22 | obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o |
23 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o | ||
24 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 23 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
25 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o | 24 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o |
26 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o | 25 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o |
27 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 26 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
28 | 27 | ||
29 | # targets | 28 | # targets |
30 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o | ||
31 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | 29 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o |
32 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 30 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 5859c046cbc4..b693f841aeb4 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -643,6 +643,7 @@ static void __exit ip6_queue_fini(void) | |||
643 | 643 | ||
644 | MODULE_DESCRIPTION("IPv6 packet queue handler"); | 644 | MODULE_DESCRIPTION("IPv6 packet queue handler"); |
645 | MODULE_LICENSE("GPL"); | 645 | MODULE_LICENSE("GPL"); |
646 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW); | ||
646 | 647 | ||
647 | module_init(ip6_queue_init); | 648 | module_init(ip6_queue_init); |
648 | module_exit(ip6_queue_fini); | 649 | module_exit(ip6_queue_fini); |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index a33485dc81cb..dfed176aed37 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -99,7 +99,6 @@ ip6_packet_match(const struct sk_buff *skb, | |||
99 | unsigned int *protoff, | 99 | unsigned int *protoff, |
100 | int *fragoff, bool *hotdrop) | 100 | int *fragoff, bool *hotdrop) |
101 | { | 101 | { |
102 | size_t i; | ||
103 | unsigned long ret; | 102 | unsigned long ret; |
104 | const struct ipv6hdr *ipv6 = ipv6_hdr(skb); | 103 | const struct ipv6hdr *ipv6 = ipv6_hdr(skb); |
105 | 104 | ||
@@ -120,12 +119,7 @@ ip6_packet_match(const struct sk_buff *skb, | |||
120 | return false; | 119 | return false; |
121 | } | 120 | } |
122 | 121 | ||
123 | /* Look for ifname matches; this should unroll nicely. */ | 122 | ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask); |
124 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { | ||
125 | ret |= (((const unsigned long *)indev)[i] | ||
126 | ^ ((const unsigned long *)ip6info->iniface)[i]) | ||
127 | & ((const unsigned long *)ip6info->iniface_mask)[i]; | ||
128 | } | ||
129 | 123 | ||
130 | if (FWINV(ret != 0, IP6T_INV_VIA_IN)) { | 124 | if (FWINV(ret != 0, IP6T_INV_VIA_IN)) { |
131 | dprintf("VIA in mismatch (%s vs %s).%s\n", | 125 | dprintf("VIA in mismatch (%s vs %s).%s\n", |
@@ -134,11 +128,7 @@ ip6_packet_match(const struct sk_buff *skb, | |||
134 | return false; | 128 | return false; |
135 | } | 129 | } |
136 | 130 | ||
137 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { | 131 | ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask); |
138 | ret |= (((const unsigned long *)outdev)[i] | ||
139 | ^ ((const unsigned long *)ip6info->outiface)[i]) | ||
140 | & ((const unsigned long *)ip6info->outiface_mask)[i]; | ||
141 | } | ||
142 | 132 | ||
143 | if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) { | 133 | if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) { |
144 | dprintf("VIA out mismatch (%s vs %s).%s\n", | 134 | dprintf("VIA out mismatch (%s vs %s).%s\n", |
@@ -373,10 +363,12 @@ ip6t_do_table(struct sk_buff *skb, | |||
373 | mtpar.family = tgpar.family = NFPROTO_IPV6; | 363 | mtpar.family = tgpar.family = NFPROTO_IPV6; |
374 | tgpar.hooknum = hook; | 364 | tgpar.hooknum = hook; |
375 | 365 | ||
376 | read_lock_bh(&table->lock); | ||
377 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 366 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
378 | private = table->private; | 367 | |
379 | table_base = (void *)private->entries[smp_processor_id()]; | 368 | rcu_read_lock_bh(); |
369 | private = rcu_dereference(table->private); | ||
370 | table_base = rcu_dereference(private->entries[smp_processor_id()]); | ||
371 | |||
380 | e = get_entry(table_base, private->hook_entry[hook]); | 372 | e = get_entry(table_base, private->hook_entry[hook]); |
381 | 373 | ||
382 | /* For return from builtin chain */ | 374 | /* For return from builtin chain */ |
@@ -474,7 +466,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
474 | #ifdef CONFIG_NETFILTER_DEBUG | 466 | #ifdef CONFIG_NETFILTER_DEBUG |
475 | ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; | 467 | ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; |
476 | #endif | 468 | #endif |
477 | read_unlock_bh(&table->lock); | 469 | rcu_read_unlock_bh(); |
478 | 470 | ||
479 | #ifdef DEBUG_ALLOW_ALL | 471 | #ifdef DEBUG_ALLOW_ALL |
480 | return NF_ACCEPT; | 472 | return NF_ACCEPT; |
@@ -525,7 +517,9 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
525 | && unconditional(&e->ipv6)) || visited) { | 517 | && unconditional(&e->ipv6)) || visited) { |
526 | unsigned int oldpos, size; | 518 | unsigned int oldpos, size; |
527 | 519 | ||
528 | if (t->verdict < -NF_MAX_VERDICT - 1) { | 520 | if ((strcmp(t->target.u.user.name, |
521 | IP6T_STANDARD_TARGET) == 0) && | ||
522 | t->verdict < -NF_MAX_VERDICT - 1) { | ||
529 | duprintf("mark_source_chains: bad " | 523 | duprintf("mark_source_chains: bad " |
530 | "negative verdict (%i)\n", | 524 | "negative verdict (%i)\n", |
531 | t->verdict); | 525 | t->verdict); |
@@ -955,11 +949,64 @@ get_counters(const struct xt_table_info *t, | |||
955 | } | 949 | } |
956 | } | 950 | } |
957 | 951 | ||
952 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
953 | * and everything is OK. */ | ||
954 | static int | ||
955 | add_counter_to_entry(struct ip6t_entry *e, | ||
956 | const struct xt_counters addme[], | ||
957 | unsigned int *i) | ||
958 | { | ||
959 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
960 | |||
961 | (*i)++; | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | /* Take values from counters and add them back onto the current cpu */ | ||
966 | static void put_counters(struct xt_table_info *t, | ||
967 | const struct xt_counters counters[]) | ||
968 | { | ||
969 | unsigned int i, cpu; | ||
970 | |||
971 | local_bh_disable(); | ||
972 | cpu = smp_processor_id(); | ||
973 | i = 0; | ||
974 | IP6T_ENTRY_ITERATE(t->entries[cpu], | ||
975 | t->size, | ||
976 | add_counter_to_entry, | ||
977 | counters, | ||
978 | &i); | ||
979 | local_bh_enable(); | ||
980 | } | ||
981 | |||
982 | static inline int | ||
983 | zero_entry_counter(struct ip6t_entry *e, void *arg) | ||
984 | { | ||
985 | e->counters.bcnt = 0; | ||
986 | e->counters.pcnt = 0; | ||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | static void | ||
991 | clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||
992 | { | ||
993 | unsigned int cpu; | ||
994 | const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||
995 | |||
996 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||
997 | for_each_possible_cpu(cpu) { | ||
998 | memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||
999 | IP6T_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||
1000 | zero_entry_counter, NULL); | ||
1001 | } | ||
1002 | } | ||
1003 | |||
958 | static struct xt_counters *alloc_counters(struct xt_table *table) | 1004 | static struct xt_counters *alloc_counters(struct xt_table *table) |
959 | { | 1005 | { |
960 | unsigned int countersize; | 1006 | unsigned int countersize; |
961 | struct xt_counters *counters; | 1007 | struct xt_counters *counters; |
962 | const struct xt_table_info *private = table->private; | 1008 | struct xt_table_info *private = table->private; |
1009 | struct xt_table_info *info; | ||
963 | 1010 | ||
964 | /* We need atomic snapshot of counters: rest doesn't change | 1011 | /* We need atomic snapshot of counters: rest doesn't change |
965 | (other than comefrom, which userspace doesn't care | 1012 | (other than comefrom, which userspace doesn't care |
@@ -968,14 +1015,28 @@ static struct xt_counters *alloc_counters(struct xt_table *table) | |||
968 | counters = vmalloc_node(countersize, numa_node_id()); | 1015 | counters = vmalloc_node(countersize, numa_node_id()); |
969 | 1016 | ||
970 | if (counters == NULL) | 1017 | if (counters == NULL) |
971 | return ERR_PTR(-ENOMEM); | 1018 | goto nomem; |
972 | 1019 | ||
973 | /* First, sum counters... */ | 1020 | info = xt_alloc_table_info(private->size); |
974 | write_lock_bh(&table->lock); | 1021 | if (!info) |
975 | get_counters(private, counters); | 1022 | goto free_counters; |
976 | write_unlock_bh(&table->lock); | 1023 | |
1024 | clone_counters(info, private); | ||
1025 | |||
1026 | mutex_lock(&table->lock); | ||
1027 | xt_table_entry_swap_rcu(private, info); | ||
1028 | synchronize_net(); /* Wait until smoke has cleared */ | ||
1029 | |||
1030 | get_counters(info, counters); | ||
1031 | put_counters(private, counters); | ||
1032 | mutex_unlock(&table->lock); | ||
977 | 1033 | ||
978 | return counters; | 1034 | xt_free_table_info(info); |
1035 | |||
1036 | free_counters: | ||
1037 | vfree(counters); | ||
1038 | nomem: | ||
1039 | return ERR_PTR(-ENOMEM); | ||
979 | } | 1040 | } |
980 | 1041 | ||
981 | static int | 1042 | static int |
@@ -1342,28 +1403,6 @@ do_replace(struct net *net, void __user *user, unsigned int len) | |||
1342 | return ret; | 1403 | return ret; |
1343 | } | 1404 | } |
1344 | 1405 | ||
1345 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
1346 | * and everything is OK. */ | ||
1347 | static inline int | ||
1348 | add_counter_to_entry(struct ip6t_entry *e, | ||
1349 | const struct xt_counters addme[], | ||
1350 | unsigned int *i) | ||
1351 | { | ||
1352 | #if 0 | ||
1353 | duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n", | ||
1354 | *i, | ||
1355 | (long unsigned int)e->counters.pcnt, | ||
1356 | (long unsigned int)e->counters.bcnt, | ||
1357 | (long unsigned int)addme[*i].pcnt, | ||
1358 | (long unsigned int)addme[*i].bcnt); | ||
1359 | #endif | ||
1360 | |||
1361 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
1362 | |||
1363 | (*i)++; | ||
1364 | return 0; | ||
1365 | } | ||
1366 | |||
1367 | static int | 1406 | static int |
1368 | do_add_counters(struct net *net, void __user *user, unsigned int len, | 1407 | do_add_counters(struct net *net, void __user *user, unsigned int len, |
1369 | int compat) | 1408 | int compat) |
@@ -1424,13 +1463,14 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, | |||
1424 | goto free; | 1463 | goto free; |
1425 | } | 1464 | } |
1426 | 1465 | ||
1427 | write_lock_bh(&t->lock); | 1466 | mutex_lock(&t->lock); |
1428 | private = t->private; | 1467 | private = t->private; |
1429 | if (private->number != num_counters) { | 1468 | if (private->number != num_counters) { |
1430 | ret = -EINVAL; | 1469 | ret = -EINVAL; |
1431 | goto unlock_up_free; | 1470 | goto unlock_up_free; |
1432 | } | 1471 | } |
1433 | 1472 | ||
1473 | preempt_disable(); | ||
1434 | i = 0; | 1474 | i = 0; |
1435 | /* Choose the copy that is on our node */ | 1475 | /* Choose the copy that is on our node */ |
1436 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; | 1476 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
@@ -1439,8 +1479,9 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, | |||
1439 | add_counter_to_entry, | 1479 | add_counter_to_entry, |
1440 | paddc, | 1480 | paddc, |
1441 | &i); | 1481 | &i); |
1482 | preempt_enable(); | ||
1442 | unlock_up_free: | 1483 | unlock_up_free: |
1443 | write_unlock_bh(&t->lock); | 1484 | mutex_unlock(&t->lock); |
1444 | xt_table_unlock(t); | 1485 | xt_table_unlock(t); |
1445 | module_put(t->me); | 1486 | module_put(t->me); |
1446 | free: | 1487 | free: |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c deleted file mode 100644 index 27b5adf670a2..000000000000 --- a/net/ipv6/netfilter/ip6t_HL.c +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* | ||
2 | * Hop Limit modification target for ip6tables | ||
3 | * Maciej Soltysiak <solt@dns.toxicfilms.tv> | ||
4 | * Based on HW's TTL module | ||
5 | * | ||
6 | * This software is distributed under the terms of GNU GPL | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/ip.h> | ||
12 | #include <linux/ipv6.h> | ||
13 | |||
14 | #include <linux/netfilter/x_tables.h> | ||
15 | #include <linux/netfilter_ipv6/ip6t_HL.h> | ||
16 | |||
17 | MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | ||
18 | MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field modification target"); | ||
19 | MODULE_LICENSE("GPL"); | ||
20 | |||
21 | static unsigned int | ||
22 | hl_tg6(struct sk_buff *skb, const struct xt_target_param *par) | ||
23 | { | ||
24 | struct ipv6hdr *ip6h; | ||
25 | const struct ip6t_HL_info *info = par->targinfo; | ||
26 | int new_hl; | ||
27 | |||
28 | if (!skb_make_writable(skb, skb->len)) | ||
29 | return NF_DROP; | ||
30 | |||
31 | ip6h = ipv6_hdr(skb); | ||
32 | |||
33 | switch (info->mode) { | ||
34 | case IP6T_HL_SET: | ||
35 | new_hl = info->hop_limit; | ||
36 | break; | ||
37 | case IP6T_HL_INC: | ||
38 | new_hl = ip6h->hop_limit + info->hop_limit; | ||
39 | if (new_hl > 255) | ||
40 | new_hl = 255; | ||
41 | break; | ||
42 | case IP6T_HL_DEC: | ||
43 | new_hl = ip6h->hop_limit - info->hop_limit; | ||
44 | if (new_hl < 0) | ||
45 | new_hl = 0; | ||
46 | break; | ||
47 | default: | ||
48 | new_hl = ip6h->hop_limit; | ||
49 | break; | ||
50 | } | ||
51 | |||
52 | ip6h->hop_limit = new_hl; | ||
53 | |||
54 | return XT_CONTINUE; | ||
55 | } | ||
56 | |||
57 | static bool hl_tg6_check(const struct xt_tgchk_param *par) | ||
58 | { | ||
59 | const struct ip6t_HL_info *info = par->targinfo; | ||
60 | |||
61 | if (info->mode > IP6T_HL_MAXMODE) { | ||
62 | printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", | ||
63 | info->mode); | ||
64 | return false; | ||
65 | } | ||
66 | if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { | ||
67 | printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " | ||
68 | "make sense with value 0\n"); | ||
69 | return false; | ||
70 | } | ||
71 | return true; | ||
72 | } | ||
73 | |||
74 | static struct xt_target hl_tg6_reg __read_mostly = { | ||
75 | .name = "HL", | ||
76 | .family = NFPROTO_IPV6, | ||
77 | .target = hl_tg6, | ||
78 | .targetsize = sizeof(struct ip6t_HL_info), | ||
79 | .table = "mangle", | ||
80 | .checkentry = hl_tg6_check, | ||
81 | .me = THIS_MODULE | ||
82 | }; | ||
83 | |||
84 | static int __init hl_tg6_init(void) | ||
85 | { | ||
86 | return xt_register_target(&hl_tg6_reg); | ||
87 | } | ||
88 | |||
89 | static void __exit hl_tg6_exit(void) | ||
90 | { | ||
91 | xt_unregister_target(&hl_tg6_reg); | ||
92 | } | ||
93 | |||
94 | module_init(hl_tg6_init); | ||
95 | module_exit(hl_tg6_exit); | ||
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 37adf5abc51e..7018cac4fddc 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -477,7 +477,7 @@ static struct xt_target log_tg6_reg __read_mostly = { | |||
477 | .me = THIS_MODULE, | 477 | .me = THIS_MODULE, |
478 | }; | 478 | }; |
479 | 479 | ||
480 | static const struct nf_logger ip6t_logger = { | 480 | static struct nf_logger ip6t_logger __read_mostly = { |
481 | .name = "ip6t_LOG", | 481 | .name = "ip6t_LOG", |
482 | .logfn = &ip6t_log_packet, | 482 | .logfn = &ip6t_log_packet, |
483 | .me = THIS_MODULE, | 483 | .me = THIS_MODULE, |
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c deleted file mode 100644 index c964dca1132d..000000000000 --- a/net/ipv6/netfilter/ip6t_hl.c +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /* Hop Limit matching module */ | ||
2 | |||
3 | /* (C) 2001-2002 Maciej Soltysiak <solt@dns.toxicfilms.tv> | ||
4 | * Based on HW's ttl module | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ipv6.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | |||
15 | #include <linux/netfilter_ipv6/ip6t_hl.h> | ||
16 | #include <linux/netfilter/x_tables.h> | ||
17 | |||
18 | MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | ||
19 | MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field match"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | ||
23 | { | ||
24 | const struct ip6t_hl_info *info = par->matchinfo; | ||
25 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
26 | |||
27 | switch (info->mode) { | ||
28 | case IP6T_HL_EQ: | ||
29 | return ip6h->hop_limit == info->hop_limit; | ||
30 | break; | ||
31 | case IP6T_HL_NE: | ||
32 | return ip6h->hop_limit != info->hop_limit; | ||
33 | break; | ||
34 | case IP6T_HL_LT: | ||
35 | return ip6h->hop_limit < info->hop_limit; | ||
36 | break; | ||
37 | case IP6T_HL_GT: | ||
38 | return ip6h->hop_limit > info->hop_limit; | ||
39 | break; | ||
40 | default: | ||
41 | printk(KERN_WARNING "ip6t_hl: unknown mode %d\n", | ||
42 | info->mode); | ||
43 | return false; | ||
44 | } | ||
45 | |||
46 | return false; | ||
47 | } | ||
48 | |||
49 | static struct xt_match hl_mt6_reg __read_mostly = { | ||
50 | .name = "hl", | ||
51 | .family = NFPROTO_IPV6, | ||
52 | .match = hl_mt6, | ||
53 | .matchsize = sizeof(struct ip6t_hl_info), | ||
54 | .me = THIS_MODULE, | ||
55 | }; | ||
56 | |||
57 | static int __init hl_mt6_init(void) | ||
58 | { | ||
59 | return xt_register_match(&hl_mt6_reg); | ||
60 | } | ||
61 | |||
62 | static void __exit hl_mt6_exit(void) | ||
63 | { | ||
64 | xt_unregister_match(&hl_mt6_reg); | ||
65 | } | ||
66 | |||
67 | module_init(hl_mt6_init); | ||
68 | module_exit(hl_mt6_exit); | ||
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 40d2e36d8fac..ef5a0a32bf8e 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -54,7 +54,6 @@ static struct | |||
54 | static struct xt_table packet_filter = { | 54 | static struct xt_table packet_filter = { |
55 | .name = "filter", | 55 | .name = "filter", |
56 | .valid_hooks = FILTER_VALID_HOOKS, | 56 | .valid_hooks = FILTER_VALID_HOOKS, |
57 | .lock = __RW_LOCK_UNLOCKED(packet_filter.lock), | ||
58 | .me = THIS_MODULE, | 57 | .me = THIS_MODULE, |
59 | .af = AF_INET6, | 58 | .af = AF_INET6, |
60 | }; | 59 | }; |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index d0b31b259d4d..ab0d398a2ba7 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -60,7 +60,6 @@ static struct | |||
60 | static struct xt_table packet_mangler = { | 60 | static struct xt_table packet_mangler = { |
61 | .name = "mangle", | 61 | .name = "mangle", |
62 | .valid_hooks = MANGLE_VALID_HOOKS, | 62 | .valid_hooks = MANGLE_VALID_HOOKS, |
63 | .lock = __RW_LOCK_UNLOCKED(packet_mangler.lock), | ||
64 | .me = THIS_MODULE, | 63 | .me = THIS_MODULE, |
65 | .af = AF_INET6, | 64 | .af = AF_INET6, |
66 | }; | 65 | }; |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 109fab6f831a..4b792b6ca321 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -38,7 +38,6 @@ static struct | |||
38 | static struct xt_table packet_raw = { | 38 | static struct xt_table packet_raw = { |
39 | .name = "raw", | 39 | .name = "raw", |
40 | .valid_hooks = RAW_VALID_HOOKS, | 40 | .valid_hooks = RAW_VALID_HOOKS, |
41 | .lock = __RW_LOCK_UNLOCKED(packet_raw.lock), | ||
42 | .me = THIS_MODULE, | 41 | .me = THIS_MODULE, |
43 | .af = AF_INET6, | 42 | .af = AF_INET6, |
44 | }; | 43 | }; |
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 20bc52f13e43..0ea37ff15d56 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -59,7 +59,6 @@ static struct | |||
59 | static struct xt_table security_table = { | 59 | static struct xt_table security_table = { |
60 | .name = "security", | 60 | .name = "security", |
61 | .valid_hooks = SECURITY_VALID_HOOKS, | 61 | .valid_hooks = SECURITY_VALID_HOOKS, |
62 | .lock = __RW_LOCK_UNLOCKED(security_table.lock), | ||
63 | .me = THIS_MODULE, | 62 | .me = THIS_MODULE, |
64 | .af = AF_INET6, | 63 | .af = AF_INET6, |
65 | }; | 64 | }; |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 727b9530448a..2a15c2d66c69 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <net/netfilter/nf_conntrack_l4proto.h> | 26 | #include <net/netfilter/nf_conntrack_l4proto.h> |
27 | #include <net/netfilter/nf_conntrack_l3proto.h> | 27 | #include <net/netfilter/nf_conntrack_l3proto.h> |
28 | #include <net/netfilter/nf_conntrack_core.h> | 28 | #include <net/netfilter/nf_conntrack_core.h> |
29 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | ||
29 | 30 | ||
30 | static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 31 | static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
31 | struct nf_conntrack_tuple *tuple) | 32 | struct nf_conntrack_tuple *tuple) |
@@ -341,6 +342,11 @@ static int ipv6_nlattr_to_tuple(struct nlattr *tb[], | |||
341 | 342 | ||
342 | return 0; | 343 | return 0; |
343 | } | 344 | } |
345 | |||
346 | static int ipv6_nlattr_tuple_size(void) | ||
347 | { | ||
348 | return nla_policy_len(ipv6_nla_policy, CTA_IP_MAX + 1); | ||
349 | } | ||
344 | #endif | 350 | #endif |
345 | 351 | ||
346 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { | 352 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { |
@@ -352,6 +358,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { | |||
352 | .get_l4proto = ipv6_get_l4proto, | 358 | .get_l4proto = ipv6_get_l4proto, |
353 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 359 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
354 | .tuple_to_nlattr = ipv6_tuple_to_nlattr, | 360 | .tuple_to_nlattr = ipv6_tuple_to_nlattr, |
361 | .nlattr_tuple_size = ipv6_nlattr_tuple_size, | ||
355 | .nlattr_to_tuple = ipv6_nlattr_to_tuple, | 362 | .nlattr_to_tuple = ipv6_nlattr_to_tuple, |
356 | .nla_policy = ipv6_nla_policy, | 363 | .nla_policy = ipv6_nla_policy, |
357 | #endif | 364 | #endif |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 72dbb6d1a6b3..9903227bf37c 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -126,6 +126,10 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
126 | pr_debug("icmpv6: can't create new conn with type %u\n", | 126 | pr_debug("icmpv6: can't create new conn with type %u\n", |
127 | type + 128); | 127 | type + 128); |
128 | nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); | 128 | nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); |
129 | if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6)) | ||
130 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | ||
131 | "nf_ct_icmpv6: invalid new with type %d ", | ||
132 | type + 128); | ||
129 | return false; | 133 | return false; |
130 | } | 134 | } |
131 | atomic_set(&ct->proto.icmp.count, 0); | 135 | atomic_set(&ct->proto.icmp.count, 0); |
@@ -265,6 +269,11 @@ static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], | |||
265 | 269 | ||
266 | return 0; | 270 | return 0; |
267 | } | 271 | } |
272 | |||
273 | static int icmpv6_nlattr_tuple_size(void) | ||
274 | { | ||
275 | return nla_policy_len(icmpv6_nla_policy, CTA_PROTO_MAX + 1); | ||
276 | } | ||
268 | #endif | 277 | #endif |
269 | 278 | ||
270 | #ifdef CONFIG_SYSCTL | 279 | #ifdef CONFIG_SYSCTL |
@@ -296,6 +305,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = | |||
296 | .error = icmpv6_error, | 305 | .error = icmpv6_error, |
297 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 306 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
298 | .tuple_to_nlattr = icmpv6_tuple_to_nlattr, | 307 | .tuple_to_nlattr = icmpv6_tuple_to_nlattr, |
308 | .nlattr_tuple_size = icmpv6_nlattr_tuple_size, | ||
299 | .nlattr_to_tuple = icmpv6_nlattr_to_tuple, | 309 | .nlattr_to_tuple = icmpv6_nlattr_to_tuple, |
300 | .nla_policy = icmpv6_nla_policy, | 310 | .nla_policy = icmpv6_nla_policy, |
301 | #endif | 311 | #endif |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9c574235c905..1394ddb6e35c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -98,7 +98,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
98 | 98 | ||
99 | static struct dst_ops ip6_dst_ops_template = { | 99 | static struct dst_ops ip6_dst_ops_template = { |
100 | .family = AF_INET6, | 100 | .family = AF_INET6, |
101 | .protocol = __constant_htons(ETH_P_IPV6), | 101 | .protocol = cpu_to_be16(ETH_P_IPV6), |
102 | .gc = ip6_dst_gc, | 102 | .gc = ip6_dst_gc, |
103 | .gc_thresh = 1024, | 103 | .gc_thresh = 1024, |
104 | .check = ip6_dst_check, | 104 | .check = ip6_dst_check, |
@@ -117,7 +117,7 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
117 | 117 | ||
118 | static struct dst_ops ip6_dst_blackhole_ops = { | 118 | static struct dst_ops ip6_dst_blackhole_ops = { |
119 | .family = AF_INET6, | 119 | .family = AF_INET6, |
120 | .protocol = __constant_htons(ETH_P_IPV6), | 120 | .protocol = cpu_to_be16(ETH_P_IPV6), |
121 | .destroy = ip6_dst_destroy, | 121 | .destroy = ip6_dst_destroy, |
122 | .check = ip6_dst_check, | 122 | .check = ip6_dst_check, |
123 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 123 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
@@ -2400,8 +2400,9 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2400 | kfree_skb(skb); | 2400 | kfree_skb(skb); |
2401 | goto errout; | 2401 | goto errout; |
2402 | } | 2402 | } |
2403 | err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, | 2403 | rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, |
2404 | info->nlh, gfp_any()); | 2404 | info->nlh, gfp_any()); |
2405 | return; | ||
2405 | errout: | 2406 | errout: |
2406 | if (err < 0) | 2407 | if (err < 0) |
2407 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); | 2408 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 5cee2bcbcece..664ab82e03b2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -454,7 +454,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
454 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 454 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
455 | goto out; | 455 | goto out; |
456 | 456 | ||
457 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 457 | if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) |
458 | t->err_count++; | 458 | t->err_count++; |
459 | else | 459 | else |
460 | t->err_count = 1; | 460 | t->err_count = 1; |
@@ -658,7 +658,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
658 | } | 658 | } |
659 | 659 | ||
660 | if (tunnel->err_count > 0) { | 660 | if (tunnel->err_count > 0) { |
661 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 661 | if (time_before(jiffies, |
662 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | ||
662 | tunnel->err_count--; | 663 | tunnel->err_count--; |
663 | dst_link_failure(skb); | 664 | dst_link_failure(skb); |
664 | } else | 665 | } else |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e5b85d45bee8..4b5aa1854260 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -533,8 +533,7 @@ static inline void syn_flood_warning(struct sk_buff *skb) | |||
533 | 533 | ||
534 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 534 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
535 | { | 535 | { |
536 | if (inet6_rsk(req)->pktopts) | 536 | kfree_skb(inet6_rsk(req)->pktopts); |
537 | kfree_skb(inet6_rsk(req)->pktopts); | ||
538 | } | 537 | } |
539 | 538 | ||
540 | #ifdef CONFIG_TCP_MD5SIG | 539 | #ifdef CONFIG_TCP_MD5SIG |
@@ -948,7 +947,7 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
948 | 947 | ||
949 | switch (skb->ip_summed) { | 948 | switch (skb->ip_summed) { |
950 | case CHECKSUM_COMPLETE: | 949 | case CHECKSUM_COMPLETE: |
951 | if (!tcp_v6_check(skb->len, &iph->saddr, &iph->daddr, | 950 | if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, |
952 | skb->csum)) { | 951 | skb->csum)) { |
953 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 952 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
954 | break; | 953 | break; |
@@ -1611,8 +1610,7 @@ ipv6_pktoptions: | |||
1611 | } | 1610 | } |
1612 | } | 1611 | } |
1613 | 1612 | ||
1614 | if (opt_skb) | 1613 | kfree_skb(opt_skb); |
1615 | kfree_skb(opt_skb); | ||
1616 | return 0; | 1614 | return 0; |
1617 | } | 1615 | } |
1618 | 1616 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 84b1a296eecb..6842dd2edd5b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -49,6 +49,34 @@ | |||
49 | #include <linux/seq_file.h> | 49 | #include <linux/seq_file.h> |
50 | #include "udp_impl.h" | 50 | #include "udp_impl.h" |
51 | 51 | ||
52 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | ||
53 | { | ||
54 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; | ||
55 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | ||
56 | int sk_ipv6only = ipv6_only_sock(sk); | ||
57 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | ||
58 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); | ||
59 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | ||
60 | |||
61 | /* if both are mapped, treat as IPv4 */ | ||
62 | if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) | ||
63 | return ipv4_rcv_saddr_equal(sk, sk2); | ||
64 | |||
65 | if (addr_type2 == IPV6_ADDR_ANY && | ||
66 | !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) | ||
67 | return 1; | ||
68 | |||
69 | if (addr_type == IPV6_ADDR_ANY && | ||
70 | !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) | ||
71 | return 1; | ||
72 | |||
73 | if (sk2_rcv_saddr6 && | ||
74 | ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6)) | ||
75 | return 1; | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
52 | int udp_v6_get_port(struct sock *sk, unsigned short snum) | 80 | int udp_v6_get_port(struct sock *sk, unsigned short snum) |
53 | { | 81 | { |
54 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); | 82 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 97ab068e8ccc..b4b16a43f277 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -272,7 +272,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
272 | 272 | ||
273 | static struct dst_ops xfrm6_dst_ops = { | 273 | static struct dst_ops xfrm6_dst_ops = { |
274 | .family = AF_INET6, | 274 | .family = AF_INET6, |
275 | .protocol = __constant_htons(ETH_P_IPV6), | 275 | .protocol = cpu_to_be16(ETH_P_IPV6), |
276 | .gc = xfrm6_garbage_collect, | 276 | .gc = xfrm6_garbage_collect, |
277 | .update_pmtu = xfrm6_update_pmtu, | 277 | .update_pmtu = xfrm6_update_pmtu, |
278 | .destroy = xfrm6_dst_destroy, | 278 | .destroy = xfrm6_dst_destroy, |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 0e685b05496e..f417b77fa0e1 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -69,7 +69,7 @@ __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass) | |||
69 | 69 | ||
70 | for (i = 0; i < n; i++) { | 70 | for (i = 0; i < n; i++) { |
71 | dst[count[class[i] - 1]++] = src[i]; | 71 | dst[count[class[i] - 1]++] = src[i]; |
72 | src[i] = 0; | 72 | src[i] = NULL; |
73 | } | 73 | } |
74 | 74 | ||
75 | return 0; | 75 | return 0; |