lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <502B1532.1030602@gmail.com>
Date:	Tue, 14 Aug 2012 23:19:14 -0400
From:	Vlad Yasevich <vyasevich@...il.com>
To:	"Eric W. Biederman" <ebiederm@...ssion.com>
CC:	David Miller <davem@...emloft.net>, linux-sctp@...r.kernel.org,
	netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
	Jan Ariyasu <jan.ariyasu@...com>,
	Jan Ariyasu <jan.ariyasu@...il.com>,
	Neil Horman <nhorman@...driver.com>,
	Thomas Graf <tgraf@...radead.org>, Xi Wang <xi.wang@...il.com>
Subject: Re: [PATCH net-next 4/9] sctp: Make the address lists per network
 namespace

On 08/06/2012 02:42 PM, Eric W. Biederman wrote:
>
> - Move the address lists into struct net
> - Add per network namespace initialization and cleanup
> - Pass around struct net so it is everywhere I need it.
> - Rename all of the global variable references into references
>    to the variables moved into struct net
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@...ssion.com>

Acked-by: Vlad Yasevich <vyasevich@...il.com>

> ---
>   include/net/net_namespace.h |    4 +
>   include/net/netns/sctp.h    |   21 +++++++
>   include/net/sctp/sctp.h     |    4 +-
>   include/net/sctp/structs.h  |   22 +-------
>   net/sctp/associola.c        |    3 +-
>   net/sctp/bind_addr.c        |   14 ++--
>   net/sctp/ipv6.c             |   17 +++---
>   net/sctp/protocol.c         |  141 +++++++++++++++++++++++++------------------
>   net/sctp/socket.c           |    7 +-
>   9 files changed, 131 insertions(+), 102 deletions(-)
>   create mode 100644 include/net/netns/sctp.h
>
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index ae1cd6c..8ab5250 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -15,6 +15,7 @@
>   #include <net/netns/packet.h>
>   #include <net/netns/ipv4.h>
>   #include <net/netns/ipv6.h>
> +#include <net/netns/sctp.h>
>   #include <net/netns/dccp.h>
>   #include <net/netns/x_tables.h>
>   #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> @@ -80,6 +81,9 @@ struct net {
>   #if IS_ENABLED(CONFIG_IPV6)
>   	struct netns_ipv6	ipv6;
>   #endif
> +#if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
> +	struct netns_sctp	sctp;
> +#endif
>   #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
>   	struct netns_dccp	dccp;
>   #endif
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> new file mode 100644
> index 0000000..cbd684e
> --- /dev/null
> +++ b/include/net/netns/sctp.h
> @@ -0,0 +1,21 @@
> +#ifndef __NETNS_SCTP_H__
> +#define __NETNS_SCTP_H__
> +
> +struct netns_sctp {
> +	/* This is the global local address list.
> +	 * We actively maintain this complete list of addresses on
> +	 * the system by catching address add/delete events.
> +	 *
> +	 * It is a list of sctp_sockaddr_entry.
> +	 */
> +	struct list_head local_addr_list;
> +	struct list_head addr_waitq;
> +	struct timer_list addr_wq_timer;
> +	struct list_head auto_asconf_splist;
> +	spinlock_t addr_wq_lock;
> +
> +	/* Lock that protects the local_addr_list writers */
> +	spinlock_t local_addr_lock;
> +};
> +
> +#endif /* __NETNS_SCTP_H__ */
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 640915a..00c9205 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -115,12 +115,12 @@
>    * sctp/protocol.c
>    */
>   extern struct sock *sctp_get_ctl_sock(void);
> -extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
> +extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
>   				     sctp_scope_t, gfp_t gfp,
>   				     int flags);
>   extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
>   extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
> -extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
> +extern void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
>
>   /*
>    * sctp/socket.c
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index c0563d1..6bdfcab 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -205,21 +205,7 @@ extern struct sctp_globals {
>   	int port_hashsize;
>   	struct sctp_bind_hashbucket *port_hashtable;
>
> -	/* This is the global local address list.
> -	 * We actively maintain this complete list of addresses on
> -	 * the system by catching address add/delete events.
> -	 *
> -	 * It is a list of sctp_sockaddr_entry.
> -	 */
> -	struct list_head local_addr_list;
>   	int default_auto_asconf;
> -	struct list_head addr_waitq;
> -	struct timer_list addr_wq_timer;
> -	struct list_head auto_asconf_splist;
> -	spinlock_t addr_wq_lock;
> -
> -	/* Lock that protects the local_addr_list writers */
> -	spinlock_t addr_list_lock;
>   	
>   	/* Flag to indicate if addip is enabled. */
>   	int addip_enable;
> @@ -278,12 +264,6 @@ extern struct sctp_globals {
>   #define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
>   #define sctp_port_hashsize		(sctp_globals.port_hashsize)
>   #define sctp_port_hashtable		(sctp_globals.port_hashtable)
> -#define sctp_local_addr_list		(sctp_globals.local_addr_list)
> -#define sctp_local_addr_lock		(sctp_globals.addr_list_lock)
> -#define sctp_auto_asconf_splist		(sctp_globals.auto_asconf_splist)
> -#define sctp_addr_waitq			(sctp_globals.addr_waitq)
> -#define sctp_addr_wq_timer		(sctp_globals.addr_wq_timer)
> -#define sctp_addr_wq_lock		(sctp_globals.addr_wq_lock)
>   #define sctp_default_auto_asconf	(sctp_globals.default_auto_asconf)
>   #define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
>   #define sctp_addip_enable		(sctp_globals.addip_enable)
> @@ -1241,7 +1221,7 @@ struct sctp_bind_addr {
>
>   void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
>   void sctp_bind_addr_free(struct sctp_bind_addr *);
> -int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
> +int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
>   			const struct sctp_bind_addr *src,
>   			sctp_scope_t scope, gfp_t gfp,
>   			int flags);
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index a3601f3..ed4930b 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1544,7 +1544,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
>   	if (asoc->peer.ipv6_address)
>   		flags |= SCTP_ADDR6_PEERSUPP;
>
> -	return sctp_bind_addr_copy(&asoc->base.bind_addr,
> +	return sctp_bind_addr_copy(sock_net(asoc->base.sk),
> +				   &asoc->base.bind_addr,
>   				   &asoc->ep->base.bind_addr,
>   				   scope, gfp, flags);
>   }
> diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
> index 4ece451..a85ce4b 100644
> --- a/net/sctp/bind_addr.c
> +++ b/net/sctp/bind_addr.c
> @@ -52,8 +52,8 @@
>   #include <net/sctp/sm.h>
>
>   /* Forward declarations for internal helpers. */
> -static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
> -			      sctp_scope_t scope, gfp_t gfp,
> +static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
> +			      union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
>   			      int flags);
>   static void sctp_bind_addr_clean(struct sctp_bind_addr *);
>
> @@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *);
>   /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
>    * in 'src' which have a broader scope than 'scope'.
>    */
> -int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
> +int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
>   			const struct sctp_bind_addr *src,
>   			sctp_scope_t scope, gfp_t gfp,
>   			int flags)
> @@ -75,7 +75,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
>
>   	/* Extract the addresses which are relevant for this scope.  */
>   	list_for_each_entry(addr, &src->address_list, list) {
> -		error = sctp_copy_one_addr(dest, &addr->a, scope,
> +		error = sctp_copy_one_addr(net, dest, &addr->a, scope,
>   					   gfp, flags);
>   		if (error < 0)
>   			goto out;
> @@ -87,7 +87,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
>   	 */
>   	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
>   		list_for_each_entry(addr, &src->address_list, list) {
> -			error = sctp_copy_one_addr(dest, &addr->a,
> +			error = sctp_copy_one_addr(net, dest, &addr->a,
>   						   SCTP_SCOPE_LINK, gfp,
>   						   flags);
>   			if (error < 0)
> @@ -448,7 +448,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
>   }
>
>   /* Copy out addresses from the global local address list. */
> -static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
> +static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
>   			      union sctp_addr *addr,
>   			      sctp_scope_t scope, gfp_t gfp,
>   			      int flags)
> @@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
>   	int error = 0;
>
>   	if (sctp_is_any(NULL, addr)) {
> -		error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
> +		error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
>   	} else if (sctp_in_scope(addr, scope)) {
>   		/* Now that the address is in scope, check to see if
>   		 * the address type is supported by local sock as
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index 2165a7e..bbf1534 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -99,6 +99,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
>   	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
>   	struct sctp_sockaddr_entry *addr = NULL;
>   	struct sctp_sockaddr_entry *temp;
> +	struct net *net = dev_net(ifa->idev->dev);
>   	int found = 0;
>
>   	switch (ev) {
> @@ -110,27 +111,27 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
>   			addr->a.v6.sin6_addr = ifa->addr;
>   			addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
>   			addr->valid = 1;
> -			spin_lock_bh(&sctp_local_addr_lock);
> -			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
> -			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
> -			spin_unlock_bh(&sctp_local_addr_lock);
> +			spin_lock_bh(&net->sctp.local_addr_lock);
> +			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
> +			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
> +			spin_unlock_bh(&net->sctp.local_addr_lock);
>   		}
>   		break;
>   	case NETDEV_DOWN:
> -		spin_lock_bh(&sctp_local_addr_lock);
> +		spin_lock_bh(&net->sctp.local_addr_lock);
>   		list_for_each_entry_safe(addr, temp,
> -					&sctp_local_addr_list, list) {
> +					&net->sctp.local_addr_list, list) {
>   			if (addr->a.sa.sa_family == AF_INET6 &&
>   					ipv6_addr_equal(&addr->a.v6.sin6_addr,
>   						&ifa->addr)) {
> -				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
> +				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
>   				found = 1;
>   				addr->valid = 0;
>   				list_del_rcu(&addr->list);
>   				break;
>   			}
>   		}
> -		spin_unlock_bh(&sctp_local_addr_lock);
> +		spin_unlock_bh(&net->sctp.local_addr_lock);
>   		if (found)
>   			kfree_rcu(addr, rcu);
>   		break;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 1f89c4e..291e682 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -201,29 +201,29 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
>   /* Extract our IP addresses from the system and stash them in the
>    * protocol structure.
>    */
> -static void sctp_get_local_addr_list(void)
> +static void sctp_get_local_addr_list(struct net *net)
>   {
>   	struct net_device *dev;
>   	struct list_head *pos;
>   	struct sctp_af *af;
>
>   	rcu_read_lock();
> -	for_each_netdev_rcu(&init_net, dev) {
> +	for_each_netdev_rcu(net, dev) {
>   		__list_for_each(pos, &sctp_address_families) {
>   			af = list_entry(pos, struct sctp_af, list);
> -			af->copy_addrlist(&sctp_local_addr_list, dev);
> +			af->copy_addrlist(&net->sctp.local_addr_list, dev);
>   		}
>   	}
>   	rcu_read_unlock();
>   }
>
>   /* Free the existing local addresses.  */
> -static void sctp_free_local_addr_list(void)
> +static void sctp_free_local_addr_list(struct net *net)
>   {
>   	struct sctp_sockaddr_entry *addr;
>   	struct list_head *pos, *temp;
>
> -	list_for_each_safe(pos, temp, &sctp_local_addr_list) {
> +	list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {
>   		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
>   		list_del(pos);
>   		kfree(addr);
> @@ -231,14 +231,14 @@ static void sctp_free_local_addr_list(void)
>   }
>
>   /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
> -int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
> -			      gfp_t gfp, int copy_flags)
> +int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> +			      sctp_scope_t scope, gfp_t gfp, int copy_flags)
>   {
>   	struct sctp_sockaddr_entry *addr;
>   	int error = 0;
>
>   	rcu_read_lock();
> -	list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
> +	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
>   		if (!addr->valid)
>   			continue;
>   		if (sctp_in_scope(&addr->a, scope)) {
> @@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk)
>
>   void sctp_addr_wq_timeout_handler(unsigned long arg)
>   {
> +	struct net *net = (struct net *)arg;
>   	struct sctp_sockaddr_entry *addrw, *temp;
>   	struct sctp_sock *sp;
>
> -	spin_lock_bh(&sctp_addr_wq_lock);
> +	spin_lock_bh(&net->sctp.addr_wq_lock);
>
> -	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
> +	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
>   		SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
> -		    " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state,
> +		    " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state,
>   		    addrw);
>
>   #if IS_ENABLED(CONFIG_IPV6)
> @@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
>   				goto free_next;
>
>   			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
> -			if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
> +			if (ipv6_chk_addr(net, in6, NULL, 0) == 0 &&
>   			    addrw->state == SCTP_ADDR_NEW) {
>   				unsigned long timeo_val;
>
> @@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
>   				    SCTP_ADDRESS_TICK_DELAY);
>   				timeo_val = jiffies;
>   				timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
> -				mod_timer(&sctp_addr_wq_timer, timeo_val);
> +				mod_timer(&net->sctp.addr_wq_timer, timeo_val);
>   				break;
>   			}
>   		}
>   #endif
> -		list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
> +		list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) {
>   			struct sock *sk;
>
>   			sk = sctp_opt2sk(sp);
> @@ -679,31 +680,32 @@ free_next:
>   		list_del(&addrw->list);
>   		kfree(addrw);
>   	}
> -	spin_unlock_bh(&sctp_addr_wq_lock);
> +	spin_unlock_bh(&net->sctp.addr_wq_lock);
>   }
>
> -static void sctp_free_addr_wq(void)
> +static void sctp_free_addr_wq(struct net *net)
>   {
>   	struct sctp_sockaddr_entry *addrw;
>   	struct sctp_sockaddr_entry *temp;
>
> -	spin_lock_bh(&sctp_addr_wq_lock);
> -	del_timer(&sctp_addr_wq_timer);
> -	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
> +	spin_lock_bh(&net->sctp.addr_wq_lock);
> +	del_timer(&net->sctp.addr_wq_timer);
> +	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
>   		list_del(&addrw->list);
>   		kfree(addrw);
>   	}
> -	spin_unlock_bh(&sctp_addr_wq_lock);
> +	spin_unlock_bh(&net->sctp.addr_wq_lock);
>   }
>
>   /* lookup the entry for the same address in the addr_waitq
>    * sctp_addr_wq MUST be locked
>    */
> -static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr)
> +static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net,
> +					struct sctp_sockaddr_entry *addr)
>   {
>   	struct sctp_sockaddr_entry *addrw;
>
> -	list_for_each_entry(addrw, &sctp_addr_waitq, list) {
> +	list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
>   		if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
>   			continue;
>   		if (addrw->a.sa.sa_family == AF_INET) {
> @@ -719,7 +721,7 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr
>   	return NULL;
>   }
>
> -void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
> +void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd)
>   {
>   	struct sctp_sockaddr_entry *addrw;
>   	unsigned long timeo_val;
> @@ -730,9 +732,9 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
>   	 * new address after a couple of addition and deletion of that address
>   	 */
>
> -	spin_lock_bh(&sctp_addr_wq_lock);
> +	spin_lock_bh(&net->sctp.addr_wq_lock);
>   	/* Offsets existing events in addr_wq */
> -	addrw = sctp_addr_wq_lookup(addr);
> +	addrw = sctp_addr_wq_lookup(net, addr);
>   	if (addrw) {
>   		if (addrw->state != cmd) {
>   			SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
> @@ -741,27 +743,27 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
>   			list_del(&addrw->list);
>   			kfree(addrw);
>   		}
> -		spin_unlock_bh(&sctp_addr_wq_lock);
> +		spin_unlock_bh(&net->sctp.addr_wq_lock);
>   		return;
>   	}
>
>   	/* OK, we have to add the new address to the wait queue */
>   	addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
>   	if (addrw == NULL) {
> -		spin_unlock_bh(&sctp_addr_wq_lock);
> +		spin_unlock_bh(&net->sctp.addr_wq_lock);
>   		return;
>   	}
>   	addrw->state = cmd;
> -	list_add_tail(&addrw->list, &sctp_addr_waitq);
> +	list_add_tail(&addrw->list, &net->sctp.addr_waitq);
>   	SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
> -	    " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq);
> +	    " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq);
>
> -	if (!timer_pending(&sctp_addr_wq_timer)) {
> +	if (!timer_pending(&net->sctp.addr_wq_timer)) {
>   		timeo_val = jiffies;
>   		timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
> -		mod_timer(&sctp_addr_wq_timer, timeo_val);
> +		mod_timer(&net->sctp.addr_wq_timer, timeo_val);
>   	}
> -	spin_unlock_bh(&sctp_addr_wq_lock);
> +	spin_unlock_bh(&net->sctp.addr_wq_lock);
>   }
>
>   /* Event handler for inet address addition/deletion events.
> @@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
>   	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
>   	struct sctp_sockaddr_entry *addr = NULL;
>   	struct sctp_sockaddr_entry *temp;
> +	struct net *net = dev_net(ifa->ifa_dev->dev);
>   	int found = 0;
>
> -	if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
> -		return NOTIFY_DONE;
> -
>   	switch (ev) {
>   	case NETDEV_UP:
>   		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
> @@ -789,27 +789,27 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
>   			addr->a.v4.sin_port = 0;
>   			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
>   			addr->valid = 1;
> -			spin_lock_bh(&sctp_local_addr_lock);
> -			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
> -			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
> -			spin_unlock_bh(&sctp_local_addr_lock);
> +			spin_lock_bh(&net->sctp.local_addr_lock);
> +			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
> +			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
> +			spin_unlock_bh(&net->sctp.local_addr_lock);
>   		}
>   		break;
>   	case NETDEV_DOWN:
> -		spin_lock_bh(&sctp_local_addr_lock);
> +		spin_lock_bh(&net->sctp.local_addr_lock);
>   		list_for_each_entry_safe(addr, temp,
> -					&sctp_local_addr_list, list) {
> +					&net->sctp.local_addr_list, list) {
>   			if (addr->a.sa.sa_family == AF_INET &&
>   					addr->a.v4.sin_addr.s_addr ==
>   					ifa->ifa_local) {
> -				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
> +				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
>   				found = 1;
>   				addr->valid = 0;
>   				list_del_rcu(&addr->list);
>   				break;
>   			}
>   		}
> -		spin_unlock_bh(&sctp_local_addr_lock);
> +		spin_unlock_bh(&net->sctp.local_addr_lock);
>   		if (found)
>   			kfree_rcu(addr, rcu);
>   		break;
> @@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void)
>   	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
>   }
>
> +static int sctp_net_init(struct net *net)
> +{
> +	/* Initialize the local address list. */
> +	INIT_LIST_HEAD(&net->sctp.local_addr_list);
> +	spin_lock_init(&net->sctp.local_addr_lock);
> +	sctp_get_local_addr_list(net);
> +
> +	/* Initialize the address event list */
> +	INIT_LIST_HEAD(&net->sctp.addr_waitq);
> +	INIT_LIST_HEAD(&net->sctp.auto_asconf_splist);
> +	spin_lock_init(&net->sctp.addr_wq_lock);
> +	net->sctp.addr_wq_timer.expires = 0;
> +	setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler,
> +		    (unsigned long)net);
> +
> +	return 0;
> +}
> +
> +static void sctp_net_exit(struct net *net)
> +{
> +	/* Free the local address list */
> +	sctp_free_addr_wq(net);
> +	sctp_free_local_addr_list(net);
> +}
> +
> +static struct pernet_operations sctp_net_ops = {
> +	.init = sctp_net_init,
> +	.exit = sctp_net_exit,
> +};
> +
>   /* Initialize the universe into something sensible.  */
>   SCTP_STATIC __init int sctp_init(void)
>   {
> @@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void)
>   	sctp_v4_pf_init();
>   	sctp_v6_pf_init();
>
> -	/* Initialize the local address list. */
> -	INIT_LIST_HEAD(&sctp_local_addr_list);
> -	spin_lock_init(&sctp_local_addr_lock);
> -	sctp_get_local_addr_list();
> -
> -	/* Initialize the address event list */
> -	INIT_LIST_HEAD(&sctp_addr_waitq);
> -	INIT_LIST_HEAD(&sctp_auto_asconf_splist);
> -	spin_lock_init(&sctp_addr_wq_lock);
> -	sctp_addr_wq_timer.expires = 0;
> -	setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
> -
>   	status = sctp_v4_protosw_init();
>
>   	if (status)
> @@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void)
>   		goto err_ctl_sock_init;
>   	}
>
> +	status = register_pernet_subsys(&sctp_net_ops);
> +	if (status)
> +		goto err_register_pernet_subsys;
> +
>   	status = sctp_v4_add_protocol();
>   	if (status)
>   		goto err_add_protocol;
> @@ -1441,13 +1463,14 @@ out:
>   err_v6_add_protocol:
>   	sctp_v4_del_protocol();
>   err_add_protocol:
> +	unregister_pernet_subsys(&sctp_net_ops);
> +err_register_pernet_subsys:
>   	inet_ctl_sock_destroy(sctp_ctl_sock);
>   err_ctl_sock_init:
>   	sctp_v6_protosw_exit();
>   err_v6_protosw_init:
>   	sctp_v4_protosw_exit();
>   err_protosw_init:
> -	sctp_free_local_addr_list();
>   	sctp_v4_pf_exit();
>   	sctp_v6_pf_exit();
>   	sctp_sysctl_unregister();
> @@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void)
>   	/* Unregister with inet6/inet layers. */
>   	sctp_v6_del_protocol();
>   	sctp_v4_del_protocol();
> -	sctp_free_addr_wq();
>
>   	/* Free the control endpoint.  */
>   	inet_ctl_sock_destroy(sctp_ctl_sock);
>
> +	unregister_pernet_subsys(&sctp_net_ops);
> +
>   	/* Free protosw registrations */
>   	sctp_v6_protosw_exit();
>   	sctp_v4_protosw_exit();
>
> -	/* Free the local address list.  */
> -	sctp_free_local_addr_list();
> -
>   	/* Unregister with socket layer. */
>   	sctp_v6_pf_exit();
>   	sctp_v4_pf_exit();
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 4316b0f..5b6dd0e 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3471,7 +3471,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
>   		sp->do_auto_asconf = 0;
>   	} else if (val && !sp->do_auto_asconf) {
>   		list_add_tail(&sp->auto_asconf_list,
> -		    &sctp_auto_asconf_splist);
> +		    &sock_net(sk)->sctp.auto_asconf_splist);
>   		sp->do_auto_asconf = 1;
>   	}
>   	return 0;
> @@ -3964,7 +3964,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
>   	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
>   	if (sctp_default_auto_asconf) {
>   		list_add_tail(&sp->auto_asconf_list,
> -		    &sctp_auto_asconf_splist);
> +		    &sock_net(sk)->sctp.auto_asconf_splist);
>   		sp->do_auto_asconf = 1;
>   	} else
>   		sp->do_auto_asconf = 0;
> @@ -4653,9 +4653,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
>   	union sctp_addr temp;
>   	int cnt = 0;
>   	int addrlen;
> +	struct net *net = sock_net(sk);
>
>   	rcu_read_lock();
> -	list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
> +	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
>   		if (!addr->valid)
>   			continue;
>
>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ