diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 16 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 5 | ||||
-rw-r--r-- | net/ipv6/protocol.c | 8 | ||||
-rw-r--r-- | net/ipv6/raw.c | 2 | ||||
-rw-r--r-- | net/ipv6/sit.c | 1 | ||||
-rw-r--r-- | net/ipv6/tunnel6.c | 24 | ||||
-rw-r--r-- | net/ipv6/udp.c | 2 |
11 files changed, 52 insertions, 22 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ec7a91d9e865..e048ec62d109 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -836,7 +836,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
836 | { | 836 | { |
837 | struct inet6_dev *idev = ifp->idev; | 837 | struct inet6_dev *idev = ifp->idev; |
838 | struct in6_addr addr, *tmpaddr; | 838 | struct in6_addr addr, *tmpaddr; |
839 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; | 839 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp, age; |
840 | unsigned long regen_advance; | 840 | unsigned long regen_advance; |
841 | int tmp_plen; | 841 | int tmp_plen; |
842 | int ret = 0; | 842 | int ret = 0; |
@@ -886,12 +886,13 @@ retry: | |||
886 | goto out; | 886 | goto out; |
887 | } | 887 | } |
888 | memcpy(&addr.s6_addr[8], idev->rndid, 8); | 888 | memcpy(&addr.s6_addr[8], idev->rndid, 8); |
889 | age = (jiffies - ifp->tstamp) / HZ; | ||
889 | tmp_valid_lft = min_t(__u32, | 890 | tmp_valid_lft = min_t(__u32, |
890 | ifp->valid_lft, | 891 | ifp->valid_lft, |
891 | idev->cnf.temp_valid_lft); | 892 | idev->cnf.temp_valid_lft + age); |
892 | tmp_prefered_lft = min_t(__u32, | 893 | tmp_prefered_lft = min_t(__u32, |
893 | ifp->prefered_lft, | 894 | ifp->prefered_lft, |
894 | idev->cnf.temp_prefered_lft - | 895 | idev->cnf.temp_prefered_lft + age - |
895 | idev->cnf.max_desync_factor); | 896 | idev->cnf.max_desync_factor); |
896 | tmp_plen = ifp->prefix_len; | 897 | tmp_plen = ifp->prefix_len; |
897 | max_addresses = idev->cnf.max_addresses; | 898 | max_addresses = idev->cnf.max_addresses; |
@@ -1426,8 +1427,10 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1426 | { | 1427 | { |
1427 | struct inet6_dev *idev = ifp->idev; | 1428 | struct inet6_dev *idev = ifp->idev; |
1428 | 1429 | ||
1429 | if (addrconf_dad_end(ifp)) | 1430 | if (addrconf_dad_end(ifp)) { |
1431 | in6_ifa_put(ifp); | ||
1430 | return; | 1432 | return; |
1433 | } | ||
1431 | 1434 | ||
1432 | if (net_ratelimit()) | 1435 | if (net_ratelimit()) |
1433 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | 1436 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", |
@@ -2021,10 +2024,11 @@ ok: | |||
2021 | ipv6_ifa_notify(0, ift); | 2024 | ipv6_ifa_notify(0, ift); |
2022 | } | 2025 | } |
2023 | 2026 | ||
2024 | if (create && in6_dev->cnf.use_tempaddr > 0) { | 2027 | if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) { |
2025 | /* | 2028 | /* |
2026 | * When a new public address is created as described in [ADDRCONF], | 2029 | * When a new public address is created as described in [ADDRCONF], |
2027 | * also create a new temporary address. | 2030 | * also create a new temporary address. Also create a temporary |
2031 | * address if it's enabled but no temporary address currently exists. | ||
2028 | */ | 2032 | */ |
2029 | read_unlock_bh(&in6_dev->lock); | 2033 | read_unlock_bh(&in6_dev->lock); |
2030 | ipv6_create_tempaddr(ifp, NULL); | 2034 | ipv6_create_tempaddr(ifp, NULL); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index c2c0f89397b1..2a59610c2a58 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -1284,6 +1284,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1284 | t = netdev_priv(dev); | 1284 | t = netdev_priv(dev); |
1285 | 1285 | ||
1286 | ip6_tnl_unlink(ip6n, t); | 1286 | ip6_tnl_unlink(ip6n, t); |
1287 | synchronize_net(); | ||
1287 | err = ip6_tnl_change(t, &p); | 1288 | err = ip6_tnl_change(t, &p); |
1288 | ip6_tnl_link(ip6n, t); | 1289 | ip6_tnl_link(ip6n, t); |
1289 | netdev_state_change(dev); | 1290 | netdev_state_change(dev); |
@@ -1371,6 +1372,7 @@ static void ip6_tnl_dev_setup(struct net_device *dev) | |||
1371 | dev->flags |= IFF_NOARP; | 1372 | dev->flags |= IFF_NOARP; |
1372 | dev->addr_len = sizeof(struct in6_addr); | 1373 | dev->addr_len = sizeof(struct in6_addr); |
1373 | dev->features |= NETIF_F_NETNS_LOCAL; | 1374 | dev->features |= NETIF_F_NETNS_LOCAL; |
1375 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | ||
1374 | } | 1376 | } |
1375 | 1377 | ||
1376 | 1378 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 0553867a317f..d1770e061c08 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -343,6 +343,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
343 | break; | 343 | break; |
344 | 344 | ||
345 | case IPV6_TRANSPARENT: | 345 | case IPV6_TRANSPARENT: |
346 | if (!capable(CAP_NET_ADMIN)) { | ||
347 | retv = -EPERM; | ||
348 | break; | ||
349 | } | ||
346 | if (optlen < sizeof(int)) | 350 | if (optlen < sizeof(int)) |
347 | goto e_inval; | 351 | goto e_inval; |
348 | /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */ | 352 | /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */ |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 44d2eeac089b..448464844a25 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -5,10 +5,15 @@ | |||
5 | menu "IPv6: Netfilter Configuration" | 5 | menu "IPv6: Netfilter Configuration" |
6 | depends on INET && IPV6 && NETFILTER | 6 | depends on INET && IPV6 && NETFILTER |
7 | 7 | ||
8 | config NF_DEFRAG_IPV6 | ||
9 | tristate | ||
10 | default n | ||
11 | |||
8 | config NF_CONNTRACK_IPV6 | 12 | config NF_CONNTRACK_IPV6 |
9 | tristate "IPv6 connection tracking support" | 13 | tristate "IPv6 connection tracking support" |
10 | depends on INET && IPV6 && NF_CONNTRACK | 14 | depends on INET && IPV6 && NF_CONNTRACK |
11 | default m if NETFILTER_ADVANCED=n | 15 | default m if NETFILTER_ADVANCED=n |
16 | select NF_DEFRAG_IPV6 | ||
12 | ---help--- | 17 | ---help--- |
13 | Connection tracking keeps a record of what packets have passed | 18 | Connection tracking keeps a record of what packets have passed |
14 | through your machine, in order to figure out how they are related | 19 | through your machine, in order to figure out how they are related |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 3f8e4a3d83ce..0a432c9b0795 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -12,11 +12,14 @@ obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | |||
12 | 12 | ||
13 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o | 14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o |
15 | nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | ||
16 | 15 | ||
17 | # l3 independent conntrack | 16 | # l3 independent conntrack |
18 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o | 17 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o |
19 | 18 | ||
19 | # defrag | ||
20 | nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | ||
21 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | ||
22 | |||
20 | # matches | 23 | # matches |
21 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 24 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
22 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o | 25 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 489d71b844ac..3a3f129a44cb 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -625,21 +625,24 @@ int nf_ct_frag6_init(void) | |||
625 | inet_frags_init_net(&nf_init_frags); | 625 | inet_frags_init_net(&nf_init_frags); |
626 | inet_frags_init(&nf_frags); | 626 | inet_frags_init(&nf_frags); |
627 | 627 | ||
628 | #ifdef CONFIG_SYSCTL | ||
628 | nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path, | 629 | nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path, |
629 | nf_ct_frag6_sysctl_table); | 630 | nf_ct_frag6_sysctl_table); |
630 | if (!nf_ct_frag6_sysctl_header) { | 631 | if (!nf_ct_frag6_sysctl_header) { |
631 | inet_frags_fini(&nf_frags); | 632 | inet_frags_fini(&nf_frags); |
632 | return -ENOMEM; | 633 | return -ENOMEM; |
633 | } | 634 | } |
635 | #endif | ||
634 | 636 | ||
635 | return 0; | 637 | return 0; |
636 | } | 638 | } |
637 | 639 | ||
638 | void nf_ct_frag6_cleanup(void) | 640 | void nf_ct_frag6_cleanup(void) |
639 | { | 641 | { |
642 | #ifdef CONFIG_SYSCTL | ||
640 | unregister_sysctl_table(nf_ct_frag6_sysctl_header); | 643 | unregister_sysctl_table(nf_ct_frag6_sysctl_header); |
641 | nf_ct_frag6_sysctl_header = NULL; | 644 | nf_ct_frag6_sysctl_header = NULL; |
642 | 645 | #endif | |
643 | inet_frags_fini(&nf_frags); | 646 | inet_frags_fini(&nf_frags); |
644 | 647 | ||
645 | nf_init_frags.low_thresh = 0; | 648 | nf_init_frags.low_thresh = 0; |
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index 9bb936ae2452..9a7978fdc02a 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c | |||
@@ -25,13 +25,14 @@ | |||
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <net/protocol.h> | 26 | #include <net/protocol.h> |
27 | 27 | ||
28 | const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS] __read_mostly; | 28 | const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly; |
29 | 29 | ||
30 | int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol) | 30 | int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol) |
31 | { | 31 | { |
32 | int hash = protocol & (MAX_INET_PROTOS - 1); | 32 | int hash = protocol & (MAX_INET_PROTOS - 1); |
33 | 33 | ||
34 | return !cmpxchg(&inet6_protos[hash], NULL, prot) ? 0 : -1; | 34 | return !cmpxchg((const struct inet6_protocol **)&inet6_protos[hash], |
35 | NULL, prot) ? 0 : -1; | ||
35 | } | 36 | } |
36 | EXPORT_SYMBOL(inet6_add_protocol); | 37 | EXPORT_SYMBOL(inet6_add_protocol); |
37 | 38 | ||
@@ -43,7 +44,8 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol | |||
43 | { | 44 | { |
44 | int ret, hash = protocol & (MAX_INET_PROTOS - 1); | 45 | int ret, hash = protocol & (MAX_INET_PROTOS - 1); |
45 | 46 | ||
46 | ret = (cmpxchg(&inet6_protos[hash], prot, NULL) == prot) ? 0 : -1; | 47 | ret = (cmpxchg((const struct inet6_protocol **)&inet6_protos[hash], |
48 | prot, NULL) == prot) ? 0 : -1; | ||
47 | 49 | ||
48 | synchronize_net(); | 50 | synchronize_net(); |
49 | 51 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 45e6efb7f171..86c39526ba5e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -373,7 +373,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
373 | 373 | ||
374 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | 374 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) |
375 | { | 375 | { |
376 | if ((raw6_sk(sk)->checksum || sk->sk_filter) && | 376 | if ((raw6_sk(sk)->checksum || rcu_dereference_raw(sk->sk_filter)) && |
377 | skb_checksum_complete(skb)) { | 377 | skb_checksum_complete(skb)) { |
378 | atomic_inc(&sk->sk_drops); | 378 | atomic_inc(&sk->sk_drops); |
379 | kfree_skb(skb); | 379 | kfree_skb(skb); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 367a6cc584cc..d6bfaec3bbbf 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -963,6 +963,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
963 | } | 963 | } |
964 | t = netdev_priv(dev); | 964 | t = netdev_priv(dev); |
965 | ipip6_tunnel_unlink(sitn, t); | 965 | ipip6_tunnel_unlink(sitn, t); |
966 | synchronize_net(); | ||
966 | t->parms.iph.saddr = p.iph.saddr; | 967 | t->parms.iph.saddr = p.iph.saddr; |
967 | t->parms.iph.daddr = p.iph.daddr; | 968 | t->parms.iph.daddr = p.iph.daddr; |
968 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 969 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index d9864725d0c6..4f3cec12aa85 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -30,23 +30,26 @@ | |||
30 | #include <net/protocol.h> | 30 | #include <net/protocol.h> |
31 | #include <net/xfrm.h> | 31 | #include <net/xfrm.h> |
32 | 32 | ||
33 | static struct xfrm6_tunnel *tunnel6_handlers __read_mostly; | 33 | static struct xfrm6_tunnel __rcu *tunnel6_handlers __read_mostly; |
34 | static struct xfrm6_tunnel *tunnel46_handlers __read_mostly; | 34 | static struct xfrm6_tunnel __rcu *tunnel46_handlers __read_mostly; |
35 | static DEFINE_MUTEX(tunnel6_mutex); | 35 | static DEFINE_MUTEX(tunnel6_mutex); |
36 | 36 | ||
37 | int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) | 37 | int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) |
38 | { | 38 | { |
39 | struct xfrm6_tunnel **pprev; | 39 | struct xfrm6_tunnel __rcu **pprev; |
40 | struct xfrm6_tunnel *t; | ||
40 | int ret = -EEXIST; | 41 | int ret = -EEXIST; |
41 | int priority = handler->priority; | 42 | int priority = handler->priority; |
42 | 43 | ||
43 | mutex_lock(&tunnel6_mutex); | 44 | mutex_lock(&tunnel6_mutex); |
44 | 45 | ||
45 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; | 46 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; |
46 | *pprev; pprev = &(*pprev)->next) { | 47 | (t = rcu_dereference_protected(*pprev, |
47 | if ((*pprev)->priority > priority) | 48 | lockdep_is_held(&tunnel6_mutex))) != NULL; |
49 | pprev = &t->next) { | ||
50 | if (t->priority > priority) | ||
48 | break; | 51 | break; |
49 | if ((*pprev)->priority == priority) | 52 | if (t->priority == priority) |
50 | goto err; | 53 | goto err; |
51 | } | 54 | } |
52 | 55 | ||
@@ -65,14 +68,17 @@ EXPORT_SYMBOL(xfrm6_tunnel_register); | |||
65 | 68 | ||
66 | int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) | 69 | int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) |
67 | { | 70 | { |
68 | struct xfrm6_tunnel **pprev; | 71 | struct xfrm6_tunnel __rcu **pprev; |
72 | struct xfrm6_tunnel *t; | ||
69 | int ret = -ENOENT; | 73 | int ret = -ENOENT; |
70 | 74 | ||
71 | mutex_lock(&tunnel6_mutex); | 75 | mutex_lock(&tunnel6_mutex); |
72 | 76 | ||
73 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; | 77 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; |
74 | *pprev; pprev = &(*pprev)->next) { | 78 | (t = rcu_dereference_protected(*pprev, |
75 | if (*pprev == handler) { | 79 | lockdep_is_held(&tunnel6_mutex))) != NULL; |
80 | pprev = &t->next) { | ||
81 | if (t == handler) { | ||
76 | *pprev = handler->next; | 82 | *pprev = handler->next; |
77 | ret = 0; | 83 | ret = 0; |
78 | break; | 84 | break; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c84dad432114..91def93bec85 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -527,7 +527,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
527 | } | 527 | } |
528 | } | 528 | } |
529 | 529 | ||
530 | if (sk->sk_filter) { | 530 | if (rcu_dereference_raw(sk->sk_filter)) { |
531 | if (udp_lib_checksum_complete(skb)) | 531 | if (udp_lib_checksum_complete(skb)) |
532 | goto drop; | 532 | goto drop; |
533 | } | 533 | } |