aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/Kconfig18
-rw-r--r--net/ipv6/addrconf.c116
-rw-r--r--net/ipv6/af_inet6.c60
-rw-r--r--net/ipv6/ip6_input.c4
-rw-r--r--net/ipv6/ipv6_sockglue.c3
-rw-r--r--net/ipv6/ndisc.c22
-rw-r--r--net/ipv6/netfilter/Kconfig38
-rw-r--r--net/ipv6/netfilter/Makefile2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c1
-rw-r--r--net/ipv6/netfilter/ip6_tables.c137
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c95
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c68
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c1
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c1
-rw-r--r--net/ipv6/netfilter/ip6table_security.c1
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c7
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c10
-rw-r--r--net/ipv6/route.c9
-rw-r--r--net/ipv6/sit.c5
-rw-r--r--net/ipv6/tcp_ipv6.c8
-rw-r--r--net/ipv6/udp.c28
-rw-r--r--net/ipv6/xfrm6_policy.c2
-rw-r--r--net/ipv6/xfrm6_state.c2
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
22if IPV6 22if IPV6
23 23
24config IPV6_PRIVACY 24config 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
1370int 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
1406static void addrconf_dad_stop(struct inet6_ifaddr *ifp) 1375static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
@@ -1433,6 +1402,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
1433void addrconf_dad_failure(struct inet6_ifaddr *ifp) 1402void 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
2205static 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)
2231static void sit_add_v4_addrs(struct inet6_dev *idev) 2221static 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)
2302static void init_loopback(struct net_device *dev) 2276static 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
2326static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) 2292static 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;
3651errout: 3613errout:
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;
3862errout: 3825errout:
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;
3932errout: 3896errout:
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
886static struct packet_type ipv6_packet_type = { 914static 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:
147drop: 146drop:
148 rcu_read_unlock(); 147 rcu_read_unlock();
149 kfree_skb(skb); 148 kfree_skb(skb);
150out:
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
1105nla_put_failure: 1101nla_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
1628release:
1629 dst_release(dst);
1634} 1630}
1635 1631
1636static void pndisc_redo(struct sk_buff *skb) 1632static 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
97config IP6_NF_MATCH_HL 97config 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
106config IP6_NF_MATCH_IPV6HEADER 106config 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
133config 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
133config IP6_NF_TARGET_LOG 142config 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
173config 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
190config IP6_NF_RAW 182config 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
20obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o 20obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
21obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 21obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
22obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o 22obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
23obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
24obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 23obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
25obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o 24obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
26obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o 25obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
27obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 26obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
28 27
29# targets 28# targets
30obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
31obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o 29obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
32obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o 30obj-$(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
644MODULE_DESCRIPTION("IPv6 packet queue handler"); 644MODULE_DESCRIPTION("IPv6 packet queue handler");
645MODULE_LICENSE("GPL"); 645MODULE_LICENSE("GPL");
646MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW);
646 647
647module_init(ip6_queue_init); 648module_init(ip6_queue_init);
648module_exit(ip6_queue_fini); 649module_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. */
954static int
955add_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 */
966static 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
982static inline int
983zero_entry_counter(struct ip6t_entry *e, void *arg)
984{
985 e->counters.bcnt = 0;
986 e->counters.pcnt = 0;
987 return 0;
988}
989
990static void
991clone_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
958static struct xt_counters *alloc_counters(struct xt_table *table) 1004static 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
981static int 1042static 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. */
1347static inline int
1348add_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
1367static int 1406static int
1368do_add_counters(struct net *net, void __user *user, unsigned int len, 1407do_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
17MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
18MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field modification target");
19MODULE_LICENSE("GPL");
20
21static unsigned int
22hl_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
57static 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
74static 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
84static int __init hl_tg6_init(void)
85{
86 return xt_register_target(&hl_tg6_reg);
87}
88
89static void __exit hl_tg6_exit(void)
90{
91 xt_unregister_target(&hl_tg6_reg);
92}
93
94module_init(hl_tg6_init);
95module_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
480static const struct nf_logger ip6t_logger = { 480static 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
18MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
19MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field match");
20MODULE_LICENSE("GPL");
21
22static 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
49static 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
57static int __init hl_mt6_init(void)
58{
59 return xt_register_match(&hl_mt6_reg);
60}
61
62static void __exit hl_mt6_exit(void)
63{
64 xt_unregister_match(&hl_mt6_reg);
65}
66
67module_init(hl_mt6_init);
68module_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
54static struct xt_table packet_filter = { 54static 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
60static struct xt_table packet_mangler = { 60static 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
38static struct xt_table packet_raw = { 38static 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
59static struct xt_table security_table = { 59static 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
30static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 31static 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
346static 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
346struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { 352struct 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
273static 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
99static struct dst_ops ip6_dst_ops_template = { 99static 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
118static struct dst_ops ip6_dst_blackhole_ops = { 118static 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;
2405errout: 2406errout:
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
534static void tcp_v6_reqsk_destructor(struct request_sock *req) 534static 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
52int 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
52int udp_v6_get_port(struct sock *sk, unsigned short snum) 80int 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
273static struct dst_ops xfrm6_dst_ops = { 273static 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;