From 7ad6848c7e81a603605fad3f3575841aab004eea Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Wed, 6 Jan 2010 20:37:01 -0800 Subject: ip: fix mc_loop checks for tunnels with multicast outer addresses When we have L3 tunnels with different inner/outer families (i.e. IPV4/IPV6) which use a multicast address as the outer tunnel destination address, multicast packets will be loopbacked back to the sending socket even if IP*_MULTICAST_LOOP is set to disabled. The mc_loop flag is present in the family specific part of the socket (e.g. the IPv4 or IPv4 specific part). setsockopt sets the inner family mc_loop flag. When the packet is pushed through the L3 tunnel it will eventually be processed by the outer family which if different will check the flag in a different part of the socket then it was set. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index cd48801a8d6f..eb6d09728633 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -121,10 +121,9 @@ static int ip6_output2(struct sk_buff *skb) skb->dev = dev; if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { - struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); - if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && + if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && ((mroute6_socket(dev_net(dev)) && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, -- cgit v1.2.3 From 5856b606e69d3e4dc2d718b475e216eb30ee2006 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 8 Jan 2010 00:59:52 -0800 Subject: net/ipv6/tcp_ipv6.c: Use compressed IPv6 address Use "[compressed ipv6]:port" form suggested by: http://tools.ietf.org/id/draft-ietf-6man-text-addr-representation-03.txt Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index febfd595a40d..1c832bf198b3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -876,7 +876,7 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) if (genhash || memcmp(hash_location, newhash, 16) != 0) { if (net_ratelimit()) { - printk(KERN_INFO "MD5 Hash %s for (%pI6, %u)->(%pI6, %u)\n", + printk(KERN_INFO "MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n", genhash ? "failed" : "mismatch", &ip6h->saddr, ntohs(th->source), &ip6h->daddr, ntohs(th->dest)); -- cgit v1.2.3 From c3f6c21d6e60e39c81c27f18ebad9c7615eff545 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 10 Jan 2010 00:43:03 +0000 Subject: NET: ipv6, remove unnecessary check Stanse found a potential null dereference in snmp6_unregister_dev. There is a check for idev being NULL, but it is dereferenced earlier. But idev cannot be NULL when passed to snmp6_unregister_dev, so remove the test. Signed-off-by: Jiri Slaby Cc: "David S. Miller" Cc: Alexey Kuznetsov Cc: "Pekka Savola (ipv6)" Cc: James Morris Cc: Hideaki YOSHIFUJI Cc: Patrick McHardy Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/ipv6/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index c9605c3ad91f..7b197b7132e0 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -259,7 +259,7 @@ int snmp6_unregister_dev(struct inet6_dev *idev) struct net *net = dev_net(idev->dev); if (!net->mib.proc_net_devsnmp6) return -ENOENT; - if (!idev || !idev->stats.proc_dir_entry) + if (!idev->stats.proc_dir_entry) return -EINVAL; remove_proc_entry(idev->stats.proc_dir_entry->name, net->mib.proc_net_devsnmp6); -- cgit v1.2.3 From 2570a4f5428bcdb1077622342181755741e7fa60 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Jan 2010 17:27:37 -0800 Subject: ipv6: skb_dst() can be NULL in ipv6_hop_jumbo(). This fixes CERT-FI FICORA #341748 Discovered by Olli Jarva and Tuomo Untinen from the CROSS project at Codenomicon Ltd. Just like in CVE-2007-4567, we can't rely upon skb_dst() being non-NULL at this point. We fixed that in commit e76b2b2567b83448c2ee85a896433b96150c92e6 ("[IPV6]: Do no rely on skb->dst before it is assigned.") However commit 483a47d2fe794328d29950fe00ce26dd405d9437 ("ipv6: added net argument to IP6_INC_STATS_BH") put a new version of the same bug into this function. Complicating analysis further, this bug can only trigger when network namespaces are enabled in the build. When namespaces are turned off, the dev_net() does not evaluate it's argument, so the dereference would not occur. So, for a long time, namespaces couldn't be turned on unless SYSFS was disabled. Therefore, this code has largely been disabled except by people turning it on explicitly for namespace development. With help from Eugene Teo Signed-off-by: David S. Miller --- net/ipv6/exthdrs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index df159fffe4bc..4bac362b1335 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -559,6 +559,11 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev); } +static inline struct net *ipv6_skb_net(struct sk_buff *skb) +{ + return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev); +} + /* Router Alert as of RFC 2711 */ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) @@ -580,8 +585,8 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) { const unsigned char *nh = skb_network_header(skb); + struct net *net = ipv6_skb_net(skb); u32 pkt_len; - struct net *net = dev_net(skb_dst(skb)->dev); if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", -- cgit v1.2.3 From 72659ecce68588b74f6c46862c2b4cec137d7a5a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sun, 17 Jan 2010 19:09:39 -0800 Subject: tcp: account SYN-ACK timeouts & retransmissions Currently we don't increment SYN-ACK timeouts & retransmissions although we do increment the same stats for SYN. We seem to have lost the SYN-ACK accounting with the introduction of tcp_syn_recv_timer (commit 2248761e in the netdev-vger-cvs tree). This patch fixes this issue. In the process we also rename the v4/v6 syn/ack retransmit functions for clarity. We also add a new request_socket operations (syn_ack_timeout) so we can keep code in inet_connection_sock.c protocol agnostic. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/net/request_sock.h | 2 ++ include/net/tcp.h | 2 ++ net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/tcp_ipv4.c | 18 ++++++++++-------- net/ipv4/tcp_timer.c | 6 ++++++ net/ipv6/tcp_ipv6.c | 12 ++++++++++-- 6 files changed, 32 insertions(+), 10 deletions(-) (limited to 'net/ipv6') diff --git a/include/net/request_sock.h b/include/net/request_sock.h index c9b50ebd9ce9..99e6e19b57c2 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -45,6 +45,8 @@ struct request_sock_ops { void (*send_reset)(struct sock *sk, struct sk_buff *skb); void (*destructor)(struct request_sock *req); + void (*syn_ack_timeout)(struct sock *sk, + struct request_sock *req); }; /* struct request_sock - mini sock to represent a connection request diff --git a/include/net/tcp.h b/include/net/tcp.h index 788c99f98597..87d164b9bd8f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -400,6 +400,8 @@ extern int compat_tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); extern void tcp_set_keepalive(struct sock *sk, int val); +extern void tcp_syn_ack_timeout(struct sock *sk, + struct request_sock *req); extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int nonblock, diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ee16475f8fc3..8da6429269dd 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -529,6 +529,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, syn_ack_recalc(req, thresh, max_retries, queue->rskq_defer_accept, &expire, &resend); + if (req->rsk_ops->syn_ack_timeout) + req->rsk_ops->syn_ack_timeout(parent, req); if (!expire && (!resend || !req->rsk_ops->rtx_syn_ack(parent, req, NULL) || diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 382f667238ec..356f544c4c10 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -742,9 +742,9 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, * This still operates on a request_sock only, not on a big * socket. */ -static int __tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, - struct request_sock *req, - struct request_values *rvp) +static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, + struct request_sock *req, + struct request_values *rvp) { const struct inet_request_sock *ireq = inet_rsk(req); int err = -1; @@ -775,10 +775,11 @@ static int __tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, return err; } -static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, +static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req, struct request_values *rvp) { - return __tcp_v4_send_synack(sk, NULL, req, rvp); + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); + return tcp_v4_send_synack(sk, NULL, req, rvp); } /* @@ -1192,10 +1193,11 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) struct request_sock_ops tcp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct tcp_request_sock), - .rtx_syn_ack = tcp_v4_send_synack, + .rtx_syn_ack = tcp_v4_rtx_synack, .send_ack = tcp_v4_reqsk_send_ack, .destructor = tcp_v4_reqsk_destructor, .send_reset = tcp_v4_send_reset, + .syn_ack_timeout = tcp_syn_ack_timeout, }; #ifdef CONFIG_TCP_MD5SIG @@ -1373,8 +1375,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) } tcp_rsk(req)->snt_isn = isn; - if (__tcp_v4_send_synack(sk, dst, req, - (struct request_values *)&tmp_ext) || + if (tcp_v4_send_synack(sk, dst, req, + (struct request_values *)&tmp_ext) || want_cookie) goto drop_and_free; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 8816a20c2597..de7d1bf9114f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -474,6 +474,12 @@ static void tcp_synack_timer(struct sock *sk) TCP_TIMEOUT_INIT, TCP_RTO_MAX); } +void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req) +{ + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEOUTS); +} +EXPORT_SYMBOL(tcp_syn_ack_timeout); + void tcp_set_keepalive(struct sock *sk, int val) { if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1c832bf198b3..82f2dea0e39e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -520,6 +520,13 @@ done: return err; } +static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, + struct request_values *rvp) +{ + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); + return tcp_v6_send_synack(sk, req, rvp); +} + static inline void syn_flood_warning(struct sk_buff *skb) { #ifdef CONFIG_SYN_COOKIES @@ -890,10 +897,11 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), - .rtx_syn_ack = tcp_v6_send_synack, + .rtx_syn_ack = tcp_v6_rtx_synack, .send_ack = tcp_v6_reqsk_send_ack, .destructor = tcp_v6_reqsk_destructor, - .send_reset = tcp_v6_send_reset + .send_reset = tcp_v6_send_reset, + .syn_ack_timeout = tcp_syn_ack_timeout, }; #ifdef CONFIG_TCP_MD5SIG -- cgit v1.2.3 From 2c8c1e7297e19bdef3c178c3ea41d898a7716e3e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 17 Jan 2010 03:35:32 +0000 Subject: net: spread __net_init, __net_exit __net_init/__net_exit are apparently not going away, so use them to full extent. In some cases __net_init was removed, because it was called from __net_exit code. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 12 ++++++------ net/8021q/vlan.c | 4 ++-- net/8021q/vlanproc.c | 2 +- net/bridge/br_if.c | 2 +- net/core/fib_rules.c | 2 +- net/core/rtnetlink.c | 4 ++-- net/core/sock.c | 4 ++-- net/dccp/ipv4.c | 4 ++-- net/dccp/ipv6.c | 4 ++-- net/ipv4/fib_frontend.c | 4 ++-- net/ipv4/igmp.c | 4 ++-- net/ipv4/ip_fragment.c | 8 ++++---- net/ipv4/ip_gre.c | 4 ++-- net/ipv4/ipip.c | 7 +++---- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/udp.c | 4 ++-- net/ipv4/udplite.c | 4 ++-- net/ipv6/addrconf.c | 8 ++++---- net/ipv6/af_inet6.c | 4 ++-- net/ipv6/anycast.c | 2 +- net/ipv6/fib6_rules.c | 4 ++-- net/ipv6/icmp.c | 2 +- net/ipv6/ip6_fib.c | 6 +++--- net/ipv6/ip6_flowlabel.c | 9 ++++----- net/ipv6/ip6_tunnel.c | 9 ++++----- net/ipv6/mcast.c | 13 ++++++------- net/ipv6/ndisc.c | 4 ++-- net/ipv6/proc.c | 4 ++-- net/ipv6/raw.c | 4 ++-- net/ipv6/reassembly.c | 8 ++++---- net/ipv6/route.c | 6 +++--- net/ipv6/sit.c | 9 ++++----- net/ipv6/sysctl_net_ipv6.c | 4 ++-- net/ipv6/tcp_ipv6.c | 8 ++++---- net/ipv6/udp.c | 2 +- net/ipv6/udplite.c | 4 ++-- net/key/af_key.c | 6 +++--- net/packet/af_packet.c | 4 ++-- net/phonet/pn_dev.c | 4 ++-- net/sysctl_net.c | 4 ++-- net/unix/af_unix.c | 4 ++-- net/unix/sysctl_net_unix.c | 2 +- net/wireless/wext-proc.c | 4 ++-- net/xfrm/xfrm_sysctl.c | 4 ++-- 44 files changed, 107 insertions(+), 112 deletions(-) (limited to 'net/ipv6') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6a42a1453afa..99a0ff3889ee 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3307,7 +3307,7 @@ static void bond_remove_proc_entry(struct bonding *bond) /* Create the bonding directory under /proc/net, if doesn't exist yet. * Caller must hold rtnl_lock. */ -static void bond_create_proc_dir(struct bond_net *bn) +static void __net_init bond_create_proc_dir(struct bond_net *bn) { if (!bn->proc_dir) { bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net); @@ -3320,7 +3320,7 @@ static void bond_create_proc_dir(struct bond_net *bn) /* Destroy the bonding directory under /proc/net, if empty. * Caller must hold rtnl_lock. */ -static void bond_destroy_proc_dir(struct bond_net *bn) +static void __net_exit bond_destroy_proc_dir(struct bond_net *bn) { if (bn->proc_dir) { remove_proc_entry(DRV_NAME, bn->net->proc_net); @@ -3338,11 +3338,11 @@ static void bond_remove_proc_entry(struct bonding *bond) { } -static void bond_create_proc_dir(struct bond_net *bn) +static inline void bond_create_proc_dir(struct bond_net *bn) { } -static void bond_destroy_proc_dir(struct bond_net *bn) +static inline void bond_destroy_proc_dir(struct bond_net *bn) { } @@ -4955,7 +4955,7 @@ out_netdev: goto out; } -static int bond_net_init(struct net *net) +static int __net_init bond_net_init(struct net *net) { struct bond_net *bn = net_generic(net, bond_net_id); @@ -4967,7 +4967,7 @@ static int bond_net_init(struct net *net) return 0; } -static void bond_net_exit(struct net *net) +static void __net_exit bond_net_exit(struct net *net) { struct bond_net *bn = net_generic(net, bond_net_id); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 33f90e7362cc..453512266ea1 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -663,7 +663,7 @@ out: return err; } -static int vlan_init_net(struct net *net) +static int __net_init vlan_init_net(struct net *net) { struct vlan_net *vn = net_generic(net, vlan_net_id); int err; @@ -675,7 +675,7 @@ static int vlan_init_net(struct net *net) return err; } -static void vlan_exit_net(struct net *net) +static void __net_exit vlan_exit_net(struct net *net) { vlan_proc_cleanup(net); } diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index 9ec1f057c03a..afead353e215 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -140,7 +140,7 @@ void vlan_proc_cleanup(struct net *net) * Create /proc/net/vlan entries */ -int vlan_proc_init(struct net *net) +int __net_init vlan_proc_init(struct net *net) { struct vlan_net *vn = net_generic(net, vlan_net_id); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index a2cbe61f6e65..7bc0604069c7 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -467,7 +467,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) return 0; } -void br_net_exit(struct net *net) +void __net_exit br_net_exit(struct net *net) { struct net_device *dev; LIST_HEAD(list); diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 02a3b2c69c1e..9a24377146bf 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -708,7 +708,7 @@ static struct notifier_block fib_rules_notifier = { .notifier_call = fib_rules_event, }; -static int fib_rules_net_init(struct net *net) +static int __net_init fib_rules_net_init(struct net *net) { INIT_LIST_HEAD(&net->rules_ops); spin_lock_init(&net->rules_mod_lock); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 794bcb897ff0..62f3878a6010 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1386,7 +1386,7 @@ static struct notifier_block rtnetlink_dev_notifier = { }; -static int rtnetlink_net_init(struct net *net) +static int __net_init rtnetlink_net_init(struct net *net) { struct sock *sk; sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, @@ -1397,7 +1397,7 @@ static int rtnetlink_net_init(struct net *net) return 0; } -static void rtnetlink_net_exit(struct net *net) +static void __net_exit rtnetlink_net_exit(struct net *net) { netlink_kernel_release(net->rtnl); net->rtnl = NULL; diff --git a/net/core/sock.c b/net/core/sock.c index 10b1d3243a72..ceef50bd131b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2140,13 +2140,13 @@ int sock_prot_inuse_get(struct net *net, struct proto *prot) } EXPORT_SYMBOL_GPL(sock_prot_inuse_get); -static int sock_inuse_init_net(struct net *net) +static int __net_init sock_inuse_init_net(struct net *net) { net->core.inuse = alloc_percpu(struct prot_inuse); return net->core.inuse ? 0 : -ENOMEM; } -static void sock_inuse_exit_net(struct net *net) +static void __net_exit sock_inuse_exit_net(struct net *net) { free_percpu(net->core.inuse); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index dad7bc4878e0..b195c4feaa0a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -996,7 +996,7 @@ static struct inet_protosw dccp_v4_protosw = { .flags = INET_PROTOSW_ICSK, }; -static int dccp_v4_init_net(struct net *net) +static int __net_init dccp_v4_init_net(struct net *net) { int err; @@ -1005,7 +1005,7 @@ static int dccp_v4_init_net(struct net *net) return err; } -static void dccp_v4_exit_net(struct net *net) +static void __net_exit dccp_v4_exit_net(struct net *net) { inet_ctl_sock_destroy(net->dccp.v4_ctl_sk); } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index baf05cf43c28..1aec6349e858 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1189,7 +1189,7 @@ static struct inet_protosw dccp_v6_protosw = { .flags = INET_PROTOSW_ICSK, }; -static int dccp_v6_init_net(struct net *net) +static int __net_init dccp_v6_init_net(struct net *net) { int err; @@ -1198,7 +1198,7 @@ static int dccp_v6_init_net(struct net *net) return err; } -static void dccp_v6_exit_net(struct net *net) +static void __net_exit dccp_v6_exit_net(struct net *net) { inet_ctl_sock_destroy(net->dccp.v6_ctl_sk); } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 82dbf711d6d0..9b3e28ed5240 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -883,7 +883,7 @@ static void nl_fib_input(struct sk_buff *skb) netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); } -static int nl_fib_lookup_init(struct net *net) +static int __net_init nl_fib_lookup_init(struct net *net) { struct sock *sk; sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, @@ -1004,7 +1004,7 @@ fail: return err; } -static void __net_exit ip_fib_net_exit(struct net *net) +static void ip_fib_net_exit(struct net *net) { unsigned int i; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 76c08402c933..8f5468393f01 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -2603,7 +2603,7 @@ static const struct file_operations igmp_mcf_seq_fops = { .release = seq_release_net, }; -static int igmp_net_init(struct net *net) +static int __net_init igmp_net_init(struct net *net) { struct proc_dir_entry *pde; @@ -2621,7 +2621,7 @@ out_igmp: return -ENOMEM; } -static void igmp_net_exit(struct net *net) +static void __net_exit igmp_net_exit(struct net *net) { proc_net_remove(net, "mcfilter"); proc_net_remove(net, "igmp"); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 86964b353c31..891c72aea520 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -646,7 +646,7 @@ static struct ctl_table ip4_frags_ctl_table[] = { { } }; -static int ip4_frags_ns_ctl_register(struct net *net) +static int __net_init ip4_frags_ns_ctl_register(struct net *net) { struct ctl_table *table; struct ctl_table_header *hdr; @@ -676,7 +676,7 @@ err_alloc: return -ENOMEM; } -static void ip4_frags_ns_ctl_unregister(struct net *net) +static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net) { struct ctl_table *table; @@ -704,7 +704,7 @@ static inline void ip4_frags_ctl_register(void) } #endif -static int ipv4_frags_init_net(struct net *net) +static int __net_init ipv4_frags_init_net(struct net *net) { /* * Fragment cache limits. We will commit 256K at one time. Should we @@ -726,7 +726,7 @@ static int ipv4_frags_init_net(struct net *net) return ip4_frags_ns_ctl_register(net); } -static void ipv4_frags_exit_net(struct net *net) +static void __net_exit ipv4_frags_exit_net(struct net *net) { ip4_frags_ns_ctl_unregister(net); inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index f36ce156cac6..7631b20490f5 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1307,7 +1307,7 @@ static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head) } } -static int ipgre_init_net(struct net *net) +static int __net_init ipgre_init_net(struct net *net) { struct ipgre_net *ign = net_generic(net, ipgre_net_id); int err; @@ -1334,7 +1334,7 @@ err_alloc_dev: return err; } -static void ipgre_exit_net(struct net *net) +static void __net_exit ipgre_exit_net(struct net *net) { struct ipgre_net *ign; LIST_HEAD(list); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index eda04fed3379..95db732e542b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -130,7 +130,6 @@ struct ipip_net { struct net_device *fb_tunnel_dev; }; -static void ipip_fb_tunnel_init(struct net_device *dev); static void ipip_tunnel_init(struct net_device *dev); static void ipip_tunnel_setup(struct net_device *dev); @@ -730,7 +729,7 @@ static void ipip_tunnel_init(struct net_device *dev) ipip_tunnel_bind_dev(dev); } -static void ipip_fb_tunnel_init(struct net_device *dev) +static void __net_init ipip_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; @@ -773,7 +772,7 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head) } } -static int ipip_init_net(struct net *net) +static int __net_init ipip_init_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); int err; @@ -806,7 +805,7 @@ err_alloc_dev: return err; } -static void ipip_exit_net(struct net *net) +static void __net_exit ipip_exit_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); LIST_HEAD(list); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 356f544c4c10..c3588b4fd979 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2430,12 +2430,12 @@ static struct tcp_seq_afinfo tcp4_seq_afinfo = { }, }; -static int tcp4_proc_init_net(struct net *net) +static int __net_init tcp4_proc_init_net(struct net *net) { return tcp_proc_register(net, &tcp4_seq_afinfo); } -static void tcp4_proc_exit_net(struct net *net) +static void __net_exit tcp4_proc_exit_net(struct net *net) { tcp_proc_unregister(net, &tcp4_seq_afinfo); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f0126fdd7e04..4f7d2122d818 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2027,12 +2027,12 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { }, }; -static int udp4_proc_init_net(struct net *net) +static int __net_init udp4_proc_init_net(struct net *net) { return udp_proc_register(net, &udp4_seq_afinfo); } -static void udp4_proc_exit_net(struct net *net) +static void __net_exit udp4_proc_exit_net(struct net *net) { udp_proc_unregister(net, &udp4_seq_afinfo); } diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 66f79513f4a5..6610bf76369f 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -81,12 +81,12 @@ static struct udp_seq_afinfo udplite4_seq_afinfo = { }, }; -static int udplite4_proc_init_net(struct net *net) +static int __net_init udplite4_proc_init_net(struct net *net) { return udp_proc_register(net, &udplite4_seq_afinfo); } -static void udplite4_proc_exit_net(struct net *net) +static void __net_exit udplite4_proc_exit_net(struct net *net) { udp_proc_unregister(net, &udplite4_seq_afinfo); } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index de7a194a64ab..1593289155ff 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3027,14 +3027,14 @@ static const struct file_operations if6_fops = { .release = seq_release_net, }; -static int if6_proc_net_init(struct net *net) +static int __net_init if6_proc_net_init(struct net *net) { if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) return -ENOMEM; return 0; } -static void if6_proc_net_exit(struct net *net) +static void __net_exit if6_proc_net_exit(struct net *net) { proc_net_remove(net, "if_inet6"); } @@ -4418,7 +4418,7 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) #endif -static int addrconf_init_net(struct net *net) +static int __net_init addrconf_init_net(struct net *net) { int err; struct ipv6_devconf *all, *dflt; @@ -4467,7 +4467,7 @@ err_alloc_all: return err; } -static void addrconf_exit_net(struct net *net) +static void __net_exit addrconf_exit_net(struct net *net) { #ifdef CONFIG_SYSCTL __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 12e69d364dd5..e29160ff4a0f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -999,7 +999,7 @@ err_udplite_mib: return -ENOMEM; } -static void __net_exit ipv6_cleanup_mibs(struct net *net) +static void ipv6_cleanup_mibs(struct net *net) { snmp_mib_free((void **)net->mib.udp_stats_in6); snmp_mib_free((void **)net->mib.udplite_stats_in6); @@ -1042,7 +1042,7 @@ out: #endif } -static void inet6_net_exit(struct net *net) +static void __net_exit inet6_net_exit(struct net *net) { #ifdef CONFIG_PROC_FS udp6_proc_exit(net); diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index f1c74c8ef9de..c4f6ca32fa74 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -538,7 +538,7 @@ static const struct file_operations ac6_seq_fops = { .release = seq_release_net, }; -int ac6_proc_init(struct net *net) +int __net_init ac6_proc_init(struct net *net) { if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops)) return -ENOMEM; diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index b7aa7c64cc4a..551882b9dfd6 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -262,7 +262,7 @@ static struct fib_rules_ops fib6_rules_ops_template = { .fro_net = &init_net, }; -static int fib6_rules_net_init(struct net *net) +static int __net_init fib6_rules_net_init(struct net *net) { struct fib_rules_ops *ops; int err = -ENOMEM; @@ -291,7 +291,7 @@ out_fib6_rules_ops: goto out; } -static void fib6_rules_net_exit(struct net *net) +static void __net_exit fib6_rules_net_exit(struct net *net) { fib_rules_unregister(net->ipv6.fib6_rules_ops); } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4ae661bc3677..217dbc2e28d4 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -951,7 +951,7 @@ ctl_table ipv6_icmp_table_template[] = { { }, }; -struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) +struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net) { struct ctl_table *table; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 0e93ca56eb69..f626ea2b304f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -239,7 +239,7 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id) return NULL; } -static void fib6_tables_init(struct net *net) +static void __net_init fib6_tables_init(struct net *net) { fib6_link_table(net, net->ipv6.fib6_main_tbl); fib6_link_table(net, net->ipv6.fib6_local_tbl); @@ -262,7 +262,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags); } -static void fib6_tables_init(struct net *net) +static void __net_init fib6_tables_init(struct net *net) { fib6_link_table(net, net->ipv6.fib6_main_tbl); } @@ -1469,7 +1469,7 @@ static void fib6_gc_timer_cb(unsigned long arg) fib6_run_gc(0, (struct net *)arg); } -static int fib6_net_init(struct net *net) +static int __net_init fib6_net_init(struct net *net) { setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 6e7bffa2205e..e41eba8aacf1 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -154,7 +154,7 @@ static void ip6_fl_gc(unsigned long dummy) write_unlock(&ip6_fl_lock); } -static void ip6_fl_purge(struct net *net) +static void __net_exit ip6_fl_purge(struct net *net) { int i; @@ -735,7 +735,7 @@ static const struct file_operations ip6fl_seq_fops = { .release = seq_release_net, }; -static int ip6_flowlabel_proc_init(struct net *net) +static int __net_init ip6_flowlabel_proc_init(struct net *net) { if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops)) @@ -743,7 +743,7 @@ static int ip6_flowlabel_proc_init(struct net *net) return 0; } -static void ip6_flowlabel_proc_fini(struct net *net) +static void __net_exit ip6_flowlabel_proc_fini(struct net *net) { proc_net_remove(net, "ip6_flowlabel"); } @@ -754,11 +754,10 @@ static inline int ip6_flowlabel_proc_init(struct net *net) } static inline void ip6_flowlabel_proc_fini(struct net *net) { - return ; } #endif -static inline void ip6_flowlabel_net_exit(struct net *net) +static void __net_exit ip6_flowlabel_net_exit(struct net *net) { ip6_fl_purge(net); ip6_flowlabel_proc_fini(net); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index d453d07b0dfe..fbd786981aa9 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -74,7 +74,6 @@ MODULE_LICENSE("GPL"); (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ (HASH_SIZE - 1)) -static void ip6_fb_tnl_dev_init(struct net_device *dev); static void ip6_tnl_dev_init(struct net_device *dev); static void ip6_tnl_dev_setup(struct net_device *dev); @@ -1364,7 +1363,7 @@ static void ip6_tnl_dev_init(struct net_device *dev) * Return: 0 **/ -static void ip6_fb_tnl_dev_init(struct net_device *dev) +static void __net_init ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); struct net *net = dev_net(dev); @@ -1388,7 +1387,7 @@ static struct xfrm6_tunnel ip6ip6_handler = { .priority = 1, }; -static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) +static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) { int h; struct ip6_tnl *t; @@ -1407,7 +1406,7 @@ static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) unregister_netdevice_many(&list); } -static int ip6_tnl_init_net(struct net *net) +static int __net_init ip6_tnl_init_net(struct net *net) { struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); int err; @@ -1436,7 +1435,7 @@ err_alloc_dev: return err; } -static void ip6_tnl_exit_net(struct net *net) +static void __net_exit ip6_tnl_exit_net(struct net *net) { struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 1f9c44442e65..25f6cca79e6b 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2646,7 +2646,7 @@ static const struct file_operations igmp6_mcf_seq_fops = { .release = seq_release_net, }; -static int igmp6_proc_init(struct net *net) +static int __net_init igmp6_proc_init(struct net *net) { int err; @@ -2666,23 +2666,22 @@ out_proc_net_igmp6: goto out; } -static void igmp6_proc_exit(struct net *net) +static void __net_exit igmp6_proc_exit(struct net *net) { proc_net_remove(net, "mcfilter6"); proc_net_remove(net, "igmp6"); } #else -static int igmp6_proc_init(struct net *net) +static inline int igmp6_proc_init(struct net *net) { return 0; } -static void igmp6_proc_exit(struct net *net) +static inline void igmp6_proc_exit(struct net *net) { - ; } #endif -static int igmp6_net_init(struct net *net) +static int __net_init igmp6_net_init(struct net *net) { int err; @@ -2708,7 +2707,7 @@ out_sock_create: goto out; } -static void igmp6_net_exit(struct net *net) +static void __net_exit igmp6_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.igmp_sk); igmp6_proc_exit(net); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index c45852798092..2dfec6bb8ada 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1772,7 +1772,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *bu #endif -static int ndisc_net_init(struct net *net) +static int __net_init ndisc_net_init(struct net *net) { struct ipv6_pinfo *np; struct sock *sk; @@ -1797,7 +1797,7 @@ static int ndisc_net_init(struct net *net) return 0; } -static void ndisc_net_exit(struct net *net) +static void __net_exit ndisc_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.ndisc_sk); } diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 7b197b7132e0..02f20016b4c9 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -267,7 +267,7 @@ int snmp6_unregister_dev(struct inet6_dev *idev) return 0; } -static int ipv6_proc_init_net(struct net *net) +static int __net_init ipv6_proc_init_net(struct net *net) { if (!proc_net_fops_create(net, "sockstat6", S_IRUGO, &sockstat6_seq_fops)) @@ -288,7 +288,7 @@ proc_dev_snmp6_fail: return -ENOMEM; } -static void ipv6_proc_exit_net(struct net *net) +static void __net_exit ipv6_proc_exit_net(struct net *net) { proc_net_remove(net, "sockstat6"); proc_net_remove(net, "dev_snmp6"); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 926ce8eeffaf..ed31c37c6e39 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1275,7 +1275,7 @@ static const struct file_operations raw6_seq_fops = { .release = seq_release_net, }; -static int raw6_init_net(struct net *net) +static int __net_init raw6_init_net(struct net *net) { if (!proc_net_fops_create(net, "raw6", S_IRUGO, &raw6_seq_fops)) return -ENOMEM; @@ -1283,7 +1283,7 @@ static int raw6_init_net(struct net *net) return 0; } -static void raw6_exit_net(struct net *net) +static void __net_exit raw6_exit_net(struct net *net) { proc_net_remove(net, "raw6"); } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 2cddea3bd6be..fa38fc7cc6e9 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -672,7 +672,7 @@ static struct ctl_table ip6_frags_ctl_table[] = { { } }; -static int ip6_frags_ns_sysctl_register(struct net *net) +static int __net_init ip6_frags_ns_sysctl_register(struct net *net) { struct ctl_table *table; struct ctl_table_header *hdr; @@ -702,7 +702,7 @@ err_alloc: return -ENOMEM; } -static void ip6_frags_ns_sysctl_unregister(struct net *net) +static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net) { struct ctl_table *table; @@ -745,7 +745,7 @@ static inline void ip6_frags_sysctl_unregister(void) } #endif -static int ipv6_frags_init_net(struct net *net) +static int __net_init ipv6_frags_init_net(struct net *net) { net->ipv6.frags.high_thresh = 256 * 1024; net->ipv6.frags.low_thresh = 192 * 1024; @@ -756,7 +756,7 @@ static int ipv6_frags_init_net(struct net *net) return ip6_frags_ns_sysctl_register(net); } -static void ipv6_frags_exit_net(struct net *net) +static void __net_exit ipv6_frags_exit_net(struct net *net) { ip6_frags_ns_sysctl_unregister(net); inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2bd74c5f8d9..8500156f2637 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2612,7 +2612,7 @@ ctl_table ipv6_route_table_template[] = { { } }; -struct ctl_table *ipv6_route_sysctl_init(struct net *net) +struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) { struct ctl_table *table; @@ -2637,7 +2637,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) } #endif -static int ip6_route_net_init(struct net *net) +static int __net_init ip6_route_net_init(struct net *net) { int ret = -ENOMEM; @@ -2702,7 +2702,7 @@ out_ip6_dst_ops: goto out; } -static void ip6_route_net_exit(struct net *net) +static void __net_exit ip6_route_net_exit(struct net *net) { #ifdef CONFIG_PROC_FS proc_net_remove(net, "ipv6_route"); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 976e68244b99..10207cc8cc0e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -62,7 +62,6 @@ #define HASH_SIZE 16 #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) -static void ipip6_fb_tunnel_init(struct net_device *dev); static void ipip6_tunnel_init(struct net_device *dev); static void ipip6_tunnel_setup(struct net_device *dev); @@ -1120,7 +1119,7 @@ static void ipip6_tunnel_init(struct net_device *dev) ipip6_tunnel_bind_dev(dev); } -static void ipip6_fb_tunnel_init(struct net_device *dev) +static void __net_init ipip6_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; @@ -1145,7 +1144,7 @@ static struct xfrm_tunnel sit_handler = { .priority = 1, }; -static void sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) +static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) { int prio; @@ -1162,7 +1161,7 @@ static void sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) } } -static int sit_init_net(struct net *net) +static int __net_init sit_init_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); int err; @@ -1195,7 +1194,7 @@ err_alloc_dev: return err; } -static void sit_exit_net(struct net *net) +static void __net_exit sit_exit_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); LIST_HEAD(list); diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index c690736885b4..f841d93bf987 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -55,7 +55,7 @@ struct ctl_path net_ipv6_ctl_path[] = { }; EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); -static int ipv6_sysctl_net_init(struct net *net) +static int __net_init ipv6_sysctl_net_init(struct net *net) { struct ctl_table *ipv6_table; struct ctl_table *ipv6_route_table; @@ -98,7 +98,7 @@ out_ipv6_table: goto out; } -static void ipv6_sysctl_net_exit(struct net *net) +static void __net_exit ipv6_sysctl_net_exit(struct net *net) { struct ctl_table *ipv6_table; struct ctl_table *ipv6_route_table; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 82f2dea0e39e..6963a6b6763e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2113,7 +2113,7 @@ static struct tcp_seq_afinfo tcp6_seq_afinfo = { }, }; -int tcp6_proc_init(struct net *net) +int __net_init tcp6_proc_init(struct net *net) { return tcp_proc_register(net, &tcp6_seq_afinfo); } @@ -2182,18 +2182,18 @@ static struct inet_protosw tcpv6_protosw = { INET_PROTOSW_ICSK, }; -static int tcpv6_net_init(struct net *net) +static int __net_init tcpv6_net_init(struct net *net) { return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6, SOCK_RAW, IPPROTO_TCP, net); } -static void tcpv6_net_exit(struct net *net) +static void __net_exit tcpv6_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.tcp_sk); } -static void tcpv6_net_exit_batch(struct list_head *net_exit_list) +static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list) { inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET6); } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 69ebdbe78c47..34efb3589ffa 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1396,7 +1396,7 @@ static struct udp_seq_afinfo udp6_seq_afinfo = { }, }; -int udp6_proc_init(struct net *net) +int __net_init udp6_proc_init(struct net *net) { return udp_proc_register(net, &udp6_seq_afinfo); } diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 6ea6938919e6..5f48fadc27f7 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -104,12 +104,12 @@ static struct udp_seq_afinfo udplite6_seq_afinfo = { }, }; -static int udplite6_proc_init_net(struct net *net) +static int __net_init udplite6_proc_init_net(struct net *net) { return udp_proc_register(net, &udplite6_seq_afinfo); } -static void udplite6_proc_exit_net(struct net *net) +static void __net_exit udplite6_proc_exit_net(struct net *net) { udp_proc_unregister(net, &udplite6_seq_afinfo); } diff --git a/net/key/af_key.c b/net/key/af_key.c index 76fa6fef6473..4744b1f6372f 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3738,17 +3738,17 @@ static int __net_init pfkey_init_proc(struct net *net) return 0; } -static void pfkey_exit_proc(struct net *net) +static void __net_exit pfkey_exit_proc(struct net *net) { proc_net_remove(net, "pfkey"); } #else -static int __net_init pfkey_init_proc(struct net *net) +static inline int pfkey_init_proc(struct net *net) { return 0; } -static void pfkey_exit_proc(struct net *net) +static inline void pfkey_exit_proc(struct net *net) { } #endif diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e0516a22be2e..a97acfe7e770 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2448,7 +2448,7 @@ static const struct file_operations packet_seq_fops = { #endif -static int packet_net_init(struct net *net) +static int __net_init packet_net_init(struct net *net) { rwlock_init(&net->packet.sklist_lock); INIT_HLIST_HEAD(&net->packet.sklist); @@ -2459,7 +2459,7 @@ static int packet_net_init(struct net *net) return 0; } -static void packet_net_exit(struct net *net) +static void __net_exit packet_net_exit(struct net *net) { proc_net_remove(net, "packet"); } diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index bc4a33bf2d3d..c597cc53a6fb 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -311,7 +311,7 @@ static struct notifier_block phonet_device_notifier = { }; /* Per-namespace Phonet devices handling */ -static int phonet_init_net(struct net *net) +static int __net_init phonet_init_net(struct net *net) { struct phonet_net *pnn = net_generic(net, phonet_net_id); @@ -324,7 +324,7 @@ static int phonet_init_net(struct net *net) return 0; } -static void phonet_exit_net(struct net *net) +static void __net_exit phonet_exit_net(struct net *net) { struct phonet_net *pnn = net_generic(net, phonet_net_id); struct net_device *dev; diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 0b15d7250c40..53196009160a 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -71,7 +71,7 @@ static struct ctl_table_root net_sysctl_ro_root = { .permissions = net_ctl_ro_header_perms, }; -static int sysctl_net_init(struct net *net) +static int __net_init sysctl_net_init(struct net *net) { setup_sysctl_set(&net->sysctls, &net_sysctl_ro_root.default_set, @@ -79,7 +79,7 @@ static int sysctl_net_init(struct net *net) return 0; } -static void sysctl_net_exit(struct net *net) +static void __net_exit sysctl_net_exit(struct net *net) { WARN_ON(!list_empty(&net->sysctls.list)); return; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f25511903115..9bc9b92bc099 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2224,7 +2224,7 @@ static const struct net_proto_family unix_family_ops = { }; -static int unix_net_init(struct net *net) +static int __net_init unix_net_init(struct net *net) { int error = -ENOMEM; @@ -2243,7 +2243,7 @@ out: return error; } -static void unix_net_exit(struct net *net) +static void __net_exit unix_net_exit(struct net *net) { unix_sysctl_unregister(net); proc_net_remove(net, "unix"); diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index 708f5df6b7f0..d095c7be10d0 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c @@ -31,7 +31,7 @@ static struct ctl_path unix_path[] = { { }, }; -int unix_sysctl_register(struct net *net) +int __net_init unix_sysctl_register(struct net *net) { struct ctl_table *table; diff --git a/net/wireless/wext-proc.c b/net/wireless/wext-proc.c index 273a7f77c834..8bafa31fa9f8 100644 --- a/net/wireless/wext-proc.c +++ b/net/wireless/wext-proc.c @@ -140,7 +140,7 @@ static const struct file_operations wireless_seq_fops = { .release = seq_release_net, }; -int wext_proc_init(struct net *net) +int __net_init wext_proc_init(struct net *net) { /* Create /proc/net/wireless entry */ if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops)) @@ -149,7 +149,7 @@ int wext_proc_init(struct net *net) return 0; } -void wext_proc_exit(struct net *net) +void __net_exit wext_proc_exit(struct net *net) { proc_net_remove(net, "wireless"); } diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c index 2e221f2cad7e..2c4d6cdcba49 100644 --- a/net/xfrm/xfrm_sysctl.c +++ b/net/xfrm/xfrm_sysctl.c @@ -2,7 +2,7 @@ #include #include -static void __xfrm_sysctl_init(struct net *net) +static void __net_init __xfrm_sysctl_init(struct net *net) { net->xfrm.sysctl_aevent_etime = XFRM_AE_ETIME; net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE; @@ -64,7 +64,7 @@ out_kmemdup: return -ENOMEM; } -void xfrm_sysctl_fini(struct net *net) +void __net_exit xfrm_sysctl_fini(struct net *net) { struct ctl_table *table; -- cgit v1.2.3 From 5833929cc2ad2b3064b4fac8c44e293972d240d8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 22 Jan 2010 10:17:26 +0000 Subject: net: constify MIB name tables Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/snmp.h | 2 +- net/ipv4/proc.c | 4 ++-- net/ipv6/proc.c | 12 ++++++------ net/sctp/proc.c | 2 +- net/xfrm/xfrm_proc.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'net/ipv6') diff --git a/include/net/snmp.h b/include/net/snmp.h index f0d756f2ac99..da02ee027d69 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -32,7 +32,7 @@ * - name of entries. */ struct snmp_mib { - char *name; + const char *name; int entry; }; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index f25542c48b7d..1b09a6dde7c0 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -127,8 +127,8 @@ static const struct snmp_mib snmp4_ipextstats_list[] = { SNMP_MIB_SENTINEL }; -static struct { - char *name; +static const struct { + const char *name; int index; } icmpmibmap[] = { { "DestUnreachs", ICMP_DEST_UNREACH }, diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 02f20016b4c9..bfe2598dd563 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -59,7 +59,7 @@ static const struct file_operations sockstat6_seq_fops = { .release = single_release_net, }; -static struct snmp_mib snmp6_ipstats_list[] = { +static const struct snmp_mib snmp6_ipstats_list[] = { /* ipv6 mib according to RFC 2465 */ SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS), SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS), @@ -92,7 +92,7 @@ static struct snmp_mib snmp6_ipstats_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp6_icmp6_list[] = { +static const struct snmp_mib snmp6_icmp6_list[] = { /* icmpv6 mib according to RFC 2466 */ SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), @@ -120,7 +120,7 @@ static const char *const icmp6type2name[256] = { }; -static struct snmp_mib snmp6_udp6_list[] = { +static const struct snmp_mib snmp6_udp6_list[] = { SNMP_MIB_ITEM("Udp6InDatagrams", UDP_MIB_INDATAGRAMS), SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS), @@ -128,7 +128,7 @@ static struct snmp_mib snmp6_udp6_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp6_udplite6_list[] = { +static const struct snmp_mib snmp6_udplite6_list[] = { SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS), SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS), @@ -170,8 +170,8 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) return; } -static inline void -snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) +static void snmp6_seq_show_item(struct seq_file *seq, void **mib, + const struct snmp_mib *itemlist) { int i; for (i=0; itemlist[i].name; i++) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index d093cbfeaac4..a5ac6e0a8d9c 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -40,7 +40,7 @@ #include #include /* for snmp_fold_field */ -static struct snmp_mib sctp_snmp_list[] = { +static const struct snmp_mib sctp_snmp_list[] = { SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB), SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS), SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS), diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index fef8db553e8d..c083a4e4e796 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -15,7 +15,7 @@ #include #include -static struct snmp_mib xfrm_mib_list[] = { +static const struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_ITEM("XfrmInError", LINUX_MIB_XFRMINERROR), SNMP_MIB_ITEM("XfrmInBufferError", LINUX_MIB_XFRMINBUFFERERROR), SNMP_MIB_ITEM("XfrmInHdrError", LINUX_MIB_XFRMINHDRERROR), -- cgit v1.2.3 From d7c7544c3d5f59033d1bf3236bc7b289f5f26b75 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 24 Jan 2010 22:47:53 -0800 Subject: netns xfrm: deal with dst entries in netns GC is non-existent in netns, so after you hit GC threshold, no new dst entries will be created until someone triggers cleanup in init_net. Make xfrm4_dst_ops and xfrm6_dst_ops per-netns. This is not done in a generic way, because it woule waste (AF_MAX - 2) * sizeof(struct dst_ops) bytes per-netns. Reorder GC threshold initialization so it'd be done before registering XFRM policies. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/netns/xfrm.h | 6 +++++ net/ipv4/xfrm4_policy.c | 14 +++++++----- net/ipv6/xfrm6_policy.c | 25 +++++++++++--------- net/xfrm/xfrm_policy.c | 59 +++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 84 insertions(+), 20 deletions(-) (limited to 'net/ipv6') diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 56f8e5585df7..74f119a2829a 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -5,6 +5,7 @@ #include #include #include +#include struct ctl_table_header; @@ -42,6 +43,11 @@ struct netns_xfrm { unsigned int policy_count[XFRM_POLICY_MAX * 2]; struct work_struct policy_hash_work; + struct dst_ops xfrm4_dst_ops; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct dst_ops xfrm6_dst_ops; +#endif + struct sock *nlsk; struct sock *nlsk_stash; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 8c08a28d8f83..67107d63c1cd 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -15,7 +15,6 @@ #include #include -static struct dst_ops xfrm4_dst_ops; static struct xfrm_policy_afinfo xfrm4_policy_afinfo; static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, @@ -190,8 +189,10 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) static inline int xfrm4_garbage_collect(struct dst_ops *ops) { - xfrm4_policy_afinfo.garbage_collect(&init_net); - return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2); + struct net *net = container_of(ops, struct net, xfrm.xfrm4_dst_ops); + + xfrm4_policy_afinfo.garbage_collect(net); + return (atomic_read(&ops->entries) > ops->gc_thresh * 2); } static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu) @@ -268,7 +269,7 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { static struct ctl_table xfrm4_policy_table[] = { { .procname = "xfrm4_gc_thresh", - .data = &xfrm4_dst_ops.gc_thresh, + .data = &init_net.xfrm.xfrm4_dst_ops.gc_thresh, .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, @@ -295,8 +296,6 @@ static void __exit xfrm4_policy_fini(void) void __init xfrm4_init(int rt_max_size) { - xfrm4_state_init(); - xfrm4_policy_init(); /* * Select a default value for the gc_thresh based on the main route * table hash size. It seems to me the worst case scenario is when @@ -308,6 +307,9 @@ void __init xfrm4_init(int rt_max_size) * and start cleaning when were 1/2 full */ xfrm4_dst_ops.gc_thresh = rt_max_size/2; + + xfrm4_state_init(); + xfrm4_policy_init(); #ifdef CONFIG_SYSCTL sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv4_ctl_path, xfrm4_policy_table); diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 7254e3f899a7..dbdc696f5fc5 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -24,7 +24,6 @@ #include #endif -static struct dst_ops xfrm6_dst_ops; static struct xfrm_policy_afinfo xfrm6_policy_afinfo; static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, @@ -224,8 +223,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) static inline int xfrm6_garbage_collect(struct dst_ops *ops) { - xfrm6_policy_afinfo.garbage_collect(&init_net); - return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2); + struct net *net = container_of(ops, struct net, xfrm.xfrm6_dst_ops); + + xfrm6_policy_afinfo.garbage_collect(net); + return (atomic_read(&ops->entries) > ops->gc_thresh * 2); } static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu) @@ -310,7 +311,7 @@ static void xfrm6_policy_fini(void) static struct ctl_table xfrm6_policy_table[] = { { .procname = "xfrm6_gc_thresh", - .data = &xfrm6_dst_ops.gc_thresh, + .data = &init_net.xfrm.xfrm6_dst_ops.gc_thresh, .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, @@ -326,13 +327,6 @@ int __init xfrm6_init(void) int ret; unsigned int gc_thresh; - ret = xfrm6_policy_init(); - if (ret) - goto out; - - ret = xfrm6_state_init(); - if (ret) - goto out_policy; /* * We need a good default value for the xfrm6 gc threshold. * In ipv4 we set it to the route hash table size * 8, which @@ -346,6 +340,15 @@ int __init xfrm6_init(void) */ gc_thresh = FIB6_TABLE_HASHSZ * 8; xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh; + + ret = xfrm6_policy_init(); + if (ret) + goto out; + + ret = xfrm6_state_init(); + if (ret) + goto out_policy; + #ifdef CONFIG_SYSCTL sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv6_ctl_path, xfrm6_policy_table); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index d2c8cb57ee4c..0ecb16a9a883 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1309,15 +1309,28 @@ static inline int xfrm_get_tos(struct flowi *fl, int family) return tos; } -static inline struct xfrm_dst *xfrm_alloc_dst(int family) +static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) { struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); + struct dst_ops *dst_ops; struct xfrm_dst *xdst; if (!afinfo) return ERR_PTR(-EINVAL); - xdst = dst_alloc(afinfo->dst_ops) ?: ERR_PTR(-ENOBUFS); + switch (family) { + case AF_INET: + dst_ops = &net->xfrm.xfrm4_dst_ops; + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + dst_ops = &net->xfrm.xfrm6_dst_ops; + break; +#endif + default: + BUG(); + } + xdst = dst_alloc(dst_ops) ?: ERR_PTR(-ENOBUFS); xfrm_policy_put_afinfo(afinfo); @@ -1366,6 +1379,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, struct flowi *fl, struct dst_entry *dst) { + struct net *net = xp_net(policy); unsigned long now = jiffies; struct net_device *dev; struct dst_entry *dst_prev = NULL; @@ -1389,7 +1403,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, dst_hold(dst); for (; i < nx; i++) { - struct xfrm_dst *xdst = xfrm_alloc_dst(family); + struct xfrm_dst *xdst = xfrm_alloc_dst(net, family); struct dst_entry *dst1 = &xdst->u.dst; err = PTR_ERR(xdst); @@ -2279,6 +2293,7 @@ EXPORT_SYMBOL(xfrm_bundle_ok); int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) { + struct net *net; int err = 0; if (unlikely(afinfo == NULL)) return -EINVAL; @@ -2302,6 +2317,27 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) xfrm_policy_afinfo[afinfo->family] = afinfo; } write_unlock_bh(&xfrm_policy_afinfo_lock); + + rtnl_lock(); + for_each_net(net) { + struct dst_ops *xfrm_dst_ops; + + switch (afinfo->family) { + case AF_INET: + xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops; + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops; + break; +#endif + default: + BUG(); + } + *xfrm_dst_ops = *afinfo->dst_ops; + } + rtnl_unlock(); + return err; } EXPORT_SYMBOL(xfrm_policy_register_afinfo); @@ -2332,6 +2368,22 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) } EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); +static void __net_init xfrm_dst_ops_init(struct net *net) +{ + struct xfrm_policy_afinfo *afinfo; + + read_lock_bh(&xfrm_policy_afinfo_lock); + afinfo = xfrm_policy_afinfo[AF_INET]; + if (afinfo) + net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + afinfo = xfrm_policy_afinfo[AF_INET6]; + if (afinfo) + net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; +#endif + read_unlock_bh(&xfrm_policy_afinfo_lock); +} + static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) { struct xfrm_policy_afinfo *afinfo; @@ -2494,6 +2546,7 @@ static int __net_init xfrm_net_init(struct net *net) rv = xfrm_policy_init(net); if (rv < 0) goto out_policy; + xfrm_dst_ops_init(net); rv = xfrm_sysctl_init(net); if (rv < 0) goto out_sysctl; -- cgit v1.2.3 From c92b544bd5d8e7ed7d81c77bbecab6df2a95aa53 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 26 Jan 2010 02:40:38 +0000 Subject: ipv6: conntrack: Add member of user to nf_ct_frag6_queue structure The commit 0b5ccb2(title:ipv6: reassembly: use seperate reassembly queues for conntrack and local delivery) has broken the saddr&&daddr member of nf_ct_frag6_queue when creating new queue. And then hash value generated by nf_hashfn() was not equal with that generated by fq_find(). So, a new received fragment can't be inserted to right queue. The patch fixes the bug with adding member of user to nf_ct_frag6_queue structure. Signed-off-by: Shan Wei Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter/nf_conntrack_reasm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/ipv6') diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 312c20adc83f..624a54832a7c 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -63,6 +63,7 @@ struct nf_ct_frag6_queue struct inet_frag_queue q; __be32 id; /* fragment id */ + u32 user; struct in6_addr saddr; struct in6_addr daddr; -- cgit v1.2.3 From e924960dacdf85d118a98c7262edf2f99c3015cf Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:28:21 +0000 Subject: netns xfrm: fixup xfrm6_tunnel error propagation Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv6/xfrm6_tunnel.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 438831d33593..23fb1002124c 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -353,13 +353,19 @@ static struct xfrm6_tunnel xfrm46_tunnel_handler = { static int __init xfrm6_tunnel_init(void) { - if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) + int rv; + + rv = xfrm_register_type(&xfrm6_tunnel_type, AF_INET6); + if (rv < 0) goto err; - if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) + rv = xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6); + if (rv < 0) goto unreg; - if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) + rv = xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET); + if (rv < 0) goto dereg6; - if (xfrm6_tunnel_spi_init() < 0) + rv = xfrm6_tunnel_spi_init(); + if (rv < 0) goto dereg46; return 0; @@ -370,7 +376,7 @@ dereg6: unreg: xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); err: - return -EAGAIN; + return rv; } static void __exit xfrm6_tunnel_fini(void) -- cgit v1.2.3 From a1664773907a2b69e2a3019598dcbeffa6bc724b Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:37:54 +0000 Subject: netns xfrm: xfrm6_tunnel in netns I'm not sure about rcu stuff near kmem cache destruction: * checks for non-empty hashes look bogus, they're done _before_ rcu_berrier() * unregistering netns ops is done before kmem_cache destoy (as it should), and unregistering involves rcu barriers by itself So it looks nothing should be done. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 6 +-- net/ipv6/ipcomp6.c | 4 +- net/ipv6/xfrm6_tunnel.c | 140 ++++++++++++++++++++++++++++-------------------- 3 files changed, 88 insertions(+), 62 deletions(-) (limited to 'net/ipv6') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 60c27706e7b9..fcee547ca7e3 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1408,9 +1408,9 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); -extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); -extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); -extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); +extern void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr); extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_output(struct sk_buff *skb); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 2f2a5ca2c878..1d1faf757c9a 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -81,7 +81,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) goto out; t->id.proto = IPPROTO_IPV6; - t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); + t->id.spi = xfrm6_tunnel_alloc_spi(&init_net, (xfrm_address_t *)&x->props.saddr); if (!t->id.spi) goto error; @@ -112,7 +112,7 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x) struct xfrm_state *t = NULL; __be32 spi; - spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr); + spi = xfrm6_tunnel_spi_lookup(&init_net, (xfrm_address_t *)&x->props.saddr); if (spi) t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr, spi, IPPROTO_IPV6, AF_INET6); diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 23fb1002124c..d6f9aeec69f7 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -30,6 +30,25 @@ #include #include #include +#include + +#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 +#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 + +#define XFRM6_TUNNEL_SPI_MIN 1 +#define XFRM6_TUNNEL_SPI_MAX 0xffffffff + +struct xfrm6_tunnel_net { + struct hlist_head spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; + struct hlist_head spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; + u32 spi; +}; + +static int xfrm6_tunnel_net_id __read_mostly; +static inline struct xfrm6_tunnel_net *xfrm6_tunnel_pernet(struct net *net) +{ + return net_generic(net, xfrm6_tunnel_net_id); +} /* * xfrm_tunnel_spi things are for allocating unique id ("spi") @@ -46,19 +65,8 @@ struct xfrm6_tunnel_spi { static DEFINE_SPINLOCK(xfrm6_tunnel_spi_lock); -static u32 xfrm6_tunnel_spi; - -#define XFRM6_TUNNEL_SPI_MIN 1 -#define XFRM6_TUNNEL_SPI_MAX 0xffffffff - static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; -#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 -#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 - -static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; -static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; - static inline unsigned xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) { unsigned h; @@ -77,49 +85,30 @@ static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) } -static int xfrm6_tunnel_spi_init(void) +static int __init xfrm6_tunnel_spi_init(void) { - int i; - - xfrm6_tunnel_spi = 0; xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", sizeof(struct xfrm6_tunnel_spi), 0, SLAB_HWCACHE_ALIGN, NULL); if (!xfrm6_tunnel_spi_kmem) return -ENOMEM; - - for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) - INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]); - for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) - INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byspi[i]); return 0; } static void xfrm6_tunnel_spi_fini(void) { - int i; - - for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) { - if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i])) - return; - } - for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) { - if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i])) - return; - } - rcu_barrier(); kmem_cache_destroy(xfrm6_tunnel_spi_kmem); - xfrm6_tunnel_spi_kmem = NULL; } -static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; struct hlist_node *pos; hlist_for_each_entry_rcu(x6spi, pos, - &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], list_byaddr) { if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) return x6spi; @@ -128,13 +117,13 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) return NULL; } -__be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; rcu_read_lock_bh(); - x6spi = __xfrm6_tunnel_spi_lookup(saddr); + x6spi = __xfrm6_tunnel_spi_lookup(net, saddr); spi = x6spi ? x6spi->spi : 0; rcu_read_unlock_bh(); return htonl(spi); @@ -142,14 +131,15 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); -static int __xfrm6_tunnel_spi_check(u32 spi) +static int __xfrm6_tunnel_spi_check(struct net *net, u32 spi) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; int index = xfrm6_tunnel_spi_hash_byspi(spi); struct hlist_node *pos; hlist_for_each_entry(x6spi, pos, - &xfrm6_tunnel_spi_byspi[index], + &xfrm6_tn->spi_byspi[index], list_byspi) { if (x6spi->spi == spi) return -1; @@ -157,32 +147,33 @@ static int __xfrm6_tunnel_spi_check(u32 spi) return index; } -static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +static u32 __xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); u32 spi; struct xfrm6_tunnel_spi *x6spi; int index; - if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || - xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) - xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN; + if (xfrm6_tn->spi < XFRM6_TUNNEL_SPI_MIN || + xfrm6_tn->spi >= XFRM6_TUNNEL_SPI_MAX) + xfrm6_tn->spi = XFRM6_TUNNEL_SPI_MIN; else - xfrm6_tunnel_spi++; + xfrm6_tn->spi++; - for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { - index = __xfrm6_tunnel_spi_check(spi); + for (spi = xfrm6_tn->spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { + index = __xfrm6_tunnel_spi_check(net, spi); if (index >= 0) goto alloc_spi; } - for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { - index = __xfrm6_tunnel_spi_check(spi); + for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tn->spi; spi++) { + index = __xfrm6_tunnel_spi_check(net, spi); if (index >= 0) goto alloc_spi; } spi = 0; goto out; alloc_spi: - xfrm6_tunnel_spi = spi; + xfrm6_tn->spi = spi; x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); if (!x6spi) goto out; @@ -192,26 +183,26 @@ alloc_spi: x6spi->spi = spi; atomic_set(&x6spi->refcnt, 1); - hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]); + hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tn->spi_byspi[index]); index = xfrm6_tunnel_spi_hash_byaddr(saddr); - hlist_add_head_rcu(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]); + hlist_add_head_rcu(&x6spi->list_byaddr, &xfrm6_tn->spi_byaddr[index]); out: return spi; } -__be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; spin_lock_bh(&xfrm6_tunnel_spi_lock); - x6spi = __xfrm6_tunnel_spi_lookup(saddr); + x6spi = __xfrm6_tunnel_spi_lookup(net, saddr); if (x6spi) { atomic_inc(&x6spi->refcnt); spi = x6spi->spi; } else - spi = __xfrm6_tunnel_alloc_spi(saddr); + spi = __xfrm6_tunnel_alloc_spi(net, saddr); spin_unlock_bh(&xfrm6_tunnel_spi_lock); return htonl(spi); @@ -225,15 +216,16 @@ static void x6spi_destroy_rcu(struct rcu_head *head) container_of(head, struct xfrm6_tunnel_spi, rcu_head)); } -void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) +void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; struct hlist_node *pos, *n; spin_lock_bh(&xfrm6_tunnel_spi_lock); hlist_for_each_entry_safe(x6spi, pos, n, - &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], list_byaddr) { if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { @@ -263,10 +255,11 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) static int xfrm6_tunnel_rcv(struct sk_buff *skb) { + struct net *net = dev_net(skb->dev); struct ipv6hdr *iph = ipv6_hdr(skb); __be32 spi; - spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); + spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&iph->saddr); return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; } @@ -326,7 +319,9 @@ static int xfrm6_tunnel_init_state(struct xfrm_state *x) static void xfrm6_tunnel_destroy(struct xfrm_state *x) { - xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); + struct net *net = xs_net(x); + + xfrm6_tunnel_free_spi(net, (xfrm_address_t *)&x->props.saddr); } static const struct xfrm_type xfrm6_tunnel_type = { @@ -351,6 +346,31 @@ static struct xfrm6_tunnel xfrm46_tunnel_handler = { .priority = 2, }; +static int __net_init xfrm6_tunnel_net_init(struct net *net) +{ + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); + unsigned int i; + + for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) + INIT_HLIST_HEAD(&xfrm6_tn->spi_byaddr[i]); + for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) + INIT_HLIST_HEAD(&xfrm6_tn->spi_byspi[i]); + xfrm6_tn->spi = 0; + + return 0; +} + +static void __net_exit xfrm6_tunnel_net_exit(struct net *net) +{ +} + +static struct pernet_operations xfrm6_tunnel_net_ops = { + .init = xfrm6_tunnel_net_init, + .exit = xfrm6_tunnel_net_exit, + .id = &xfrm6_tunnel_net_id, + .size = sizeof(struct xfrm6_tunnel_net), +}; + static int __init xfrm6_tunnel_init(void) { int rv; @@ -367,8 +387,13 @@ static int __init xfrm6_tunnel_init(void) rv = xfrm6_tunnel_spi_init(); if (rv < 0) goto dereg46; + rv = register_pernet_subsys(&xfrm6_tunnel_net_ops); + if (rv < 0) + goto deregspi; return 0; +deregspi: + xfrm6_tunnel_spi_fini(); dereg46: xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); dereg6: @@ -381,6 +406,7 @@ err: static void __exit xfrm6_tunnel_fini(void) { + unregister_pernet_subsys(&xfrm6_tunnel_net_ops); xfrm6_tunnel_spi_fini(); xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); -- cgit v1.2.3 From d74340d31bf1dbeb00acadddd8697666528a7846 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:39:09 +0000 Subject: netns xfrm: ipcomp6 support Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv6/ipcomp6.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 1d1faf757c9a..a9fbb151bb79 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -53,6 +53,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { + struct net *net = dev_net(skb->dev); __be32 spi; struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; struct ip_comp_hdr *ipcomph = @@ -63,7 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; spi = htonl(ntohs(ipcomph->cpi)); - x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); + x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; @@ -74,14 +75,15 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) { + struct net *net = xs_net(x); struct xfrm_state *t = NULL; - t = xfrm_state_alloc(&init_net); + t = xfrm_state_alloc(net); if (!t) goto out; t->id.proto = IPPROTO_IPV6; - t->id.spi = xfrm6_tunnel_alloc_spi(&init_net, (xfrm_address_t *)&x->props.saddr); + t->id.spi = xfrm6_tunnel_alloc_spi(net, (xfrm_address_t *)&x->props.saddr); if (!t->id.spi) goto error; @@ -108,13 +110,14 @@ error: static int ipcomp6_tunnel_attach(struct xfrm_state *x) { + struct net *net = xs_net(x); int err = 0; struct xfrm_state *t = NULL; __be32 spi; - spi = xfrm6_tunnel_spi_lookup(&init_net, (xfrm_address_t *)&x->props.saddr); + spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&x->props.saddr); if (spi) - t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr, + t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr, spi, IPPROTO_IPV6, AF_INET6); if (!t) { t = ipcomp6_tunnel_create(x); -- cgit v1.2.3 From 14c7dbe043d01a83a30633ab6b109ba2ac61d9f7 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 8 Feb 2010 11:17:43 -0800 Subject: netfilter: xtables: compat out of scope fix As per C99 6.2.4(2) when temporary table data goes out of scope, the behaviour is undefined: if (compat) { struct foo tmp; ... private = &tmp; } [dereference private] Signed-off-by: Alexey Dobriyan Cc: stable@kernel.org Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/arp_tables.c | 4 ++-- net/ipv4/netfilter/ip_tables.c | 4 ++-- net/ipv6/netfilter/ip6_tables.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 06632762ba5f..90203e1b9187 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -925,10 +925,10 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) if (t && !IS_ERR(t)) { struct arpt_getinfo info; const struct xt_table_info *private = t->private; - #ifdef CONFIG_COMPAT + struct xt_table_info tmp; + if (compat) { - struct xt_table_info tmp; ret = compat_table_info(private, &tmp); xt_compat_flush_offsets(NFPROTO_ARP); private = &tmp; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 572330a552ef..3ce53cf13d5a 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1132,10 +1132,10 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) if (t && !IS_ERR(t)) { struct ipt_getinfo info; const struct xt_table_info *private = t->private; - #ifdef CONFIG_COMPAT + struct xt_table_info tmp; + if (compat) { - struct xt_table_info tmp; ret = compat_table_info(private, &tmp); xt_compat_flush_offsets(AF_INET); private = &tmp; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 480d7f8c9802..8a7e0f52e177 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1164,10 +1164,10 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) if (t && !IS_ERR(t)) { struct ip6t_getinfo info; const struct xt_table_info *private = t->private; - #ifdef CONFIG_COMPAT + struct xt_table_info tmp; + if (compat) { - struct xt_table_info tmp; ret = compat_table_info(private, &tmp); xt_compat_flush_offsets(AF_INET6); private = &tmp; -- cgit v1.2.3