mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	sctp: Make the address lists per network namespace
- 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@xmission.com> Acked-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									4110cc255d
								
							
						
					
					
						commit
						4db67e8086
					
				
					 9 changed files with 132 additions and 103 deletions
				
			
		| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
#include <net/netns/packet.h>
 | 
					#include <net/netns/packet.h>
 | 
				
			||||||
#include <net/netns/ipv4.h>
 | 
					#include <net/netns/ipv4.h>
 | 
				
			||||||
#include <net/netns/ipv6.h>
 | 
					#include <net/netns/ipv6.h>
 | 
				
			||||||
 | 
					#include <net/netns/sctp.h>
 | 
				
			||||||
#include <net/netns/dccp.h>
 | 
					#include <net/netns/dccp.h>
 | 
				
			||||||
#include <net/netns/x_tables.h>
 | 
					#include <net/netns/x_tables.h>
 | 
				
			||||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 | 
					#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 | 
				
			||||||
| 
						 | 
					@ -81,6 +82,9 @@ struct net {
 | 
				
			||||||
#if IS_ENABLED(CONFIG_IPV6)
 | 
					#if IS_ENABLED(CONFIG_IPV6)
 | 
				
			||||||
	struct netns_ipv6	ipv6;
 | 
						struct netns_ipv6	ipv6;
 | 
				
			||||||
#endif
 | 
					#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)
 | 
					#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
 | 
				
			||||||
	struct netns_dccp	dccp;
 | 
						struct netns_dccp	dccp;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										21
									
								
								include/net/netns/sctp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/net/netns/sctp.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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__ */
 | 
				
			||||||
| 
						 | 
					@ -115,12 +115,12 @@
 | 
				
			||||||
 * sctp/protocol.c
 | 
					 * sctp/protocol.c
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
extern struct sock *sctp_get_ctl_sock(void);
 | 
					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,
 | 
									     sctp_scope_t, gfp_t gfp,
 | 
				
			||||||
				     int flags);
 | 
									     int flags);
 | 
				
			||||||
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
 | 
					extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
 | 
				
			||||||
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
 | 
					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
 | 
					 * sctp/socket.c
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,21 +205,7 @@ extern struct sctp_globals {
 | 
				
			||||||
	int port_hashsize;
 | 
						int port_hashsize;
 | 
				
			||||||
	struct sctp_bind_hashbucket *port_hashtable;
 | 
						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;
 | 
						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. */
 | 
						/* Flag to indicate if addip is enabled. */
 | 
				
			||||||
	int addip_enable;
 | 
						int addip_enable;
 | 
				
			||||||
| 
						 | 
					@ -278,12 +264,6 @@ extern struct sctp_globals {
 | 
				
			||||||
#define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
 | 
					#define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
 | 
				
			||||||
#define sctp_port_hashsize		(sctp_globals.port_hashsize)
 | 
					#define sctp_port_hashsize		(sctp_globals.port_hashsize)
 | 
				
			||||||
#define sctp_port_hashtable		(sctp_globals.port_hashtable)
 | 
					#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_default_auto_asconf	(sctp_globals.default_auto_asconf)
 | 
				
			||||||
#define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
 | 
					#define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
 | 
				
			||||||
#define sctp_addip_enable		(sctp_globals.addip_enable)
 | 
					#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_init(struct sctp_bind_addr *, __u16 port);
 | 
				
			||||||
void sctp_bind_addr_free(struct sctp_bind_addr *);
 | 
					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,
 | 
								const struct sctp_bind_addr *src,
 | 
				
			||||||
			sctp_scope_t scope, gfp_t gfp,
 | 
								sctp_scope_t scope, gfp_t gfp,
 | 
				
			||||||
			int flags);
 | 
								int flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1544,7 +1544,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
 | 
				
			||||||
	if (asoc->peer.ipv6_address)
 | 
						if (asoc->peer.ipv6_address)
 | 
				
			||||||
		flags |= SCTP_ADDR6_PEERSUPP;
 | 
							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,
 | 
									   &asoc->ep->base.bind_addr,
 | 
				
			||||||
				   scope, gfp, flags);
 | 
									   scope, gfp, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,8 +52,8 @@
 | 
				
			||||||
#include <net/sctp/sm.h>
 | 
					#include <net/sctp/sm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Forward declarations for internal helpers. */
 | 
					/* Forward declarations for internal helpers. */
 | 
				
			||||||
static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
 | 
					static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
 | 
				
			||||||
			      sctp_scope_t scope, gfp_t gfp,
 | 
								      union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
 | 
				
			||||||
			      int flags);
 | 
								      int flags);
 | 
				
			||||||
static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 | 
					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
 | 
					/* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
 | 
				
			||||||
 * in 'src' which have a broader scope than 'scope'.
 | 
					 * 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,
 | 
								const struct sctp_bind_addr *src,
 | 
				
			||||||
			sctp_scope_t scope, gfp_t gfp,
 | 
								sctp_scope_t scope, gfp_t gfp,
 | 
				
			||||||
			int flags)
 | 
								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.  */
 | 
						/* Extract the addresses which are relevant for this scope.  */
 | 
				
			||||||
	list_for_each_entry(addr, &src->address_list, list) {
 | 
						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);
 | 
										   gfp, flags);
 | 
				
			||||||
		if (error < 0)
 | 
							if (error < 0)
 | 
				
			||||||
			goto out;
 | 
								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)) {
 | 
						if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
 | 
				
			||||||
		list_for_each_entry(addr, &src->address_list, list) {
 | 
							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,
 | 
											   SCTP_SCOPE_LINK, gfp,
 | 
				
			||||||
						   flags);
 | 
											   flags);
 | 
				
			||||||
			if (error < 0)
 | 
								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. */
 | 
					/* 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,
 | 
								      union sctp_addr *addr,
 | 
				
			||||||
			      sctp_scope_t scope, gfp_t gfp,
 | 
								      sctp_scope_t scope, gfp_t gfp,
 | 
				
			||||||
			      int flags)
 | 
								      int flags)
 | 
				
			||||||
| 
						 | 
					@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
 | 
				
			||||||
	int error = 0;
 | 
						int error = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sctp_is_any(NULL, addr)) {
 | 
						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)) {
 | 
						} else if (sctp_in_scope(addr, scope)) {
 | 
				
			||||||
		/* Now that the address is in scope, check to see if
 | 
							/* Now that the address is in scope, check to see if
 | 
				
			||||||
		 * the address type is supported by local sock as
 | 
							 * the address type is supported by local sock as
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
 | 
				
			||||||
	struct sctp_sockaddr_entry *addr = NULL;
 | 
						struct sctp_sockaddr_entry *addr = NULL;
 | 
				
			||||||
	struct sctp_sockaddr_entry *temp;
 | 
						struct sctp_sockaddr_entry *temp;
 | 
				
			||||||
 | 
						struct net *net = dev_net(ifa->idev->dev);
 | 
				
			||||||
	int found = 0;
 | 
						int found = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (ev) {
 | 
						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_addr = ifa->addr;
 | 
				
			||||||
			addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
 | 
								addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
 | 
				
			||||||
			addr->valid = 1;
 | 
								addr->valid = 1;
 | 
				
			||||||
			spin_lock_bh(&sctp_local_addr_lock);
 | 
								spin_lock_bh(&net->sctp.local_addr_lock);
 | 
				
			||||||
			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
 | 
								list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
 | 
				
			||||||
			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
 | 
								sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
 | 
				
			||||||
			spin_unlock_bh(&sctp_local_addr_lock);
 | 
								spin_unlock_bh(&net->sctp.local_addr_lock);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NETDEV_DOWN:
 | 
						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,
 | 
							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 &&
 | 
								if (addr->a.sa.sa_family == AF_INET6 &&
 | 
				
			||||||
					ipv6_addr_equal(&addr->a.v6.sin6_addr,
 | 
										ipv6_addr_equal(&addr->a.v6.sin6_addr,
 | 
				
			||||||
						&ifa->addr)) {
 | 
											&ifa->addr)) {
 | 
				
			||||||
				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
 | 
									sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
 | 
				
			||||||
				found = 1;
 | 
									found = 1;
 | 
				
			||||||
				addr->valid = 0;
 | 
									addr->valid = 0;
 | 
				
			||||||
				list_del_rcu(&addr->list);
 | 
									list_del_rcu(&addr->list);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		spin_unlock_bh(&sctp_local_addr_lock);
 | 
							spin_unlock_bh(&net->sctp.local_addr_lock);
 | 
				
			||||||
		if (found)
 | 
							if (found)
 | 
				
			||||||
			kfree_rcu(addr, rcu);
 | 
								kfree_rcu(addr, rcu);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					/* Extract our IP addresses from the system and stash them in the
 | 
				
			||||||
 * protocol structure.
 | 
					 * 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 net_device *dev;
 | 
				
			||||||
	struct list_head *pos;
 | 
						struct list_head *pos;
 | 
				
			||||||
	struct sctp_af *af;
 | 
						struct sctp_af *af;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev_rcu(&init_net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		__list_for_each(pos, &sctp_address_families) {
 | 
							__list_for_each(pos, &sctp_address_families) {
 | 
				
			||||||
			af = list_entry(pos, struct sctp_af, list);
 | 
								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();
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Free the existing local addresses.  */
 | 
					/* 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 sctp_sockaddr_entry *addr;
 | 
				
			||||||
	struct list_head *pos, *temp;
 | 
						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);
 | 
							addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 | 
				
			||||||
		list_del(pos);
 | 
							list_del(pos);
 | 
				
			||||||
		kfree(addr);
 | 
							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'.  */
 | 
					/* 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,
 | 
					int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
 | 
				
			||||||
			      gfp_t gfp, int copy_flags)
 | 
								      sctp_scope_t scope, gfp_t gfp, int copy_flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sctp_sockaddr_entry *addr;
 | 
						struct sctp_sockaddr_entry *addr;
 | 
				
			||||||
	int error = 0;
 | 
						int error = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						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)
 | 
							if (!addr->valid)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (sctp_in_scope(&addr->a, scope)) {
 | 
							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)
 | 
					void sctp_addr_wq_timeout_handler(unsigned long arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct net *net = (struct net *)arg;
 | 
				
			||||||
	struct sctp_sockaddr_entry *addrw, *temp;
 | 
						struct sctp_sockaddr_entry *addrw, *temp;
 | 
				
			||||||
	struct sctp_sock *sp;
 | 
						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 ",
 | 
							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);
 | 
							    addrw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if IS_ENABLED(CONFIG_IPV6)
 | 
					#if IS_ENABLED(CONFIG_IPV6)
 | 
				
			||||||
| 
						 | 
					@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
 | 
				
			||||||
				goto free_next;
 | 
									goto free_next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
 | 
								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) {
 | 
								    addrw->state == SCTP_ADDR_NEW) {
 | 
				
			||||||
				unsigned long timeo_val;
 | 
									unsigned long timeo_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
 | 
				
			||||||
				    SCTP_ADDRESS_TICK_DELAY);
 | 
									    SCTP_ADDRESS_TICK_DELAY);
 | 
				
			||||||
				timeo_val = jiffies;
 | 
									timeo_val = jiffies;
 | 
				
			||||||
				timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
 | 
									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;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
#endif
 | 
					#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;
 | 
								struct sock *sk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sk = sctp_opt2sk(sp);
 | 
								sk = sctp_opt2sk(sp);
 | 
				
			||||||
| 
						 | 
					@ -679,31 +680,32 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
 | 
				
			||||||
		list_del(&addrw->list);
 | 
							list_del(&addrw->list);
 | 
				
			||||||
		kfree(addrw);
 | 
							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 *addrw;
 | 
				
			||||||
	struct sctp_sockaddr_entry *temp;
 | 
						struct sctp_sockaddr_entry *temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&sctp_addr_wq_lock);
 | 
						spin_lock_bh(&net->sctp.addr_wq_lock);
 | 
				
			||||||
	del_timer(&sctp_addr_wq_timer);
 | 
						del_timer(&net->sctp.addr_wq_timer);
 | 
				
			||||||
	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
 | 
						list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
 | 
				
			||||||
		list_del(&addrw->list);
 | 
							list_del(&addrw->list);
 | 
				
			||||||
		kfree(addrw);
 | 
							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
 | 
					/* lookup the entry for the same address in the addr_waitq
 | 
				
			||||||
 * sctp_addr_wq MUST be locked
 | 
					 * 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;
 | 
						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)
 | 
							if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (addrw->a.sa.sa_family == AF_INET) {
 | 
							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;
 | 
						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;
 | 
						struct sctp_sockaddr_entry *addrw;
 | 
				
			||||||
	unsigned long timeo_val;
 | 
						unsigned long timeo_val;
 | 
				
			||||||
| 
						 | 
					@ -730,38 +732,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
 | 
				
			||||||
	 * new address after a couple of addition and deletion of that address
 | 
						 * 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 */
 | 
						/* Offsets existing events in addr_wq */
 | 
				
			||||||
	addrw = sctp_addr_wq_lookup(addr);
 | 
						addrw = sctp_addr_wq_lookup(net, addr);
 | 
				
			||||||
	if (addrw) {
 | 
						if (addrw) {
 | 
				
			||||||
		if (addrw->state != cmd) {
 | 
							if (addrw->state != cmd) {
 | 
				
			||||||
			SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
 | 
								SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
 | 
				
			||||||
			    " in wq %p\n", addrw->state, &addrw->a,
 | 
								    " in wq %p\n", addrw->state, &addrw->a,
 | 
				
			||||||
			    &sctp_addr_waitq);
 | 
								    &net->sctp.addr_waitq);
 | 
				
			||||||
			list_del(&addrw->list);
 | 
								list_del(&addrw->list);
 | 
				
			||||||
			kfree(addrw);
 | 
								kfree(addrw);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		spin_unlock_bh(&sctp_addr_wq_lock);
 | 
							spin_unlock_bh(&net->sctp.addr_wq_lock);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* OK, we have to add the new address to the wait queue */
 | 
						/* OK, we have to add the new address to the wait queue */
 | 
				
			||||||
	addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
 | 
						addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
 | 
				
			||||||
	if (addrw == NULL) {
 | 
						if (addrw == NULL) {
 | 
				
			||||||
		spin_unlock_bh(&sctp_addr_wq_lock);
 | 
							spin_unlock_bh(&net->sctp.addr_wq_lock);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	addrw->state = cmd;
 | 
						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 ",
 | 
						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 = jiffies;
 | 
				
			||||||
		timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
 | 
							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.
 | 
					/* 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 in_ifaddr *ifa = (struct in_ifaddr *)ptr;
 | 
				
			||||||
	struct sctp_sockaddr_entry *addr = NULL;
 | 
						struct sctp_sockaddr_entry *addr = NULL;
 | 
				
			||||||
	struct sctp_sockaddr_entry *temp;
 | 
						struct sctp_sockaddr_entry *temp;
 | 
				
			||||||
 | 
						struct net *net = dev_net(ifa->ifa_dev->dev);
 | 
				
			||||||
	int found = 0;
 | 
						int found = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
 | 
					 | 
				
			||||||
		return NOTIFY_DONE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (ev) {
 | 
						switch (ev) {
 | 
				
			||||||
	case NETDEV_UP:
 | 
						case NETDEV_UP:
 | 
				
			||||||
		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
 | 
							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_port = 0;
 | 
				
			||||||
			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
 | 
								addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
 | 
				
			||||||
			addr->valid = 1;
 | 
								addr->valid = 1;
 | 
				
			||||||
			spin_lock_bh(&sctp_local_addr_lock);
 | 
								spin_lock_bh(&net->sctp.local_addr_lock);
 | 
				
			||||||
			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
 | 
								list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
 | 
				
			||||||
			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
 | 
								sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
 | 
				
			||||||
			spin_unlock_bh(&sctp_local_addr_lock);
 | 
								spin_unlock_bh(&net->sctp.local_addr_lock);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NETDEV_DOWN:
 | 
						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,
 | 
							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 &&
 | 
								if (addr->a.sa.sa_family == AF_INET &&
 | 
				
			||||||
					addr->a.v4.sin_addr.s_addr ==
 | 
										addr->a.v4.sin_addr.s_addr ==
 | 
				
			||||||
					ifa->ifa_local) {
 | 
										ifa->ifa_local) {
 | 
				
			||||||
				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
 | 
									sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
 | 
				
			||||||
				found = 1;
 | 
									found = 1;
 | 
				
			||||||
				addr->valid = 0;
 | 
									addr->valid = 0;
 | 
				
			||||||
				list_del_rcu(&addr->list);
 | 
									list_del_rcu(&addr->list);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		spin_unlock_bh(&sctp_local_addr_lock);
 | 
							spin_unlock_bh(&net->sctp.local_addr_lock);
 | 
				
			||||||
		if (found)
 | 
							if (found)
 | 
				
			||||||
			kfree_rcu(addr, rcu);
 | 
								kfree_rcu(addr, rcu);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void)
 | 
				
			||||||
	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
 | 
						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.  */
 | 
					/* Initialize the universe into something sensible.  */
 | 
				
			||||||
SCTP_STATIC __init int sctp_init(void)
 | 
					SCTP_STATIC __init int sctp_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void)
 | 
				
			||||||
	sctp_v4_pf_init();
 | 
						sctp_v4_pf_init();
 | 
				
			||||||
	sctp_v6_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();
 | 
						status = sctp_v4_protosw_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (status)
 | 
						if (status)
 | 
				
			||||||
| 
						 | 
					@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void)
 | 
				
			||||||
		goto err_ctl_sock_init;
 | 
							goto err_ctl_sock_init;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = register_pernet_subsys(&sctp_net_ops);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							goto err_register_pernet_subsys;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = sctp_v4_add_protocol();
 | 
						status = sctp_v4_add_protocol();
 | 
				
			||||||
	if (status)
 | 
						if (status)
 | 
				
			||||||
		goto err_add_protocol;
 | 
							goto err_add_protocol;
 | 
				
			||||||
| 
						 | 
					@ -1441,13 +1463,14 @@ SCTP_STATIC __init int sctp_init(void)
 | 
				
			||||||
err_v6_add_protocol:
 | 
					err_v6_add_protocol:
 | 
				
			||||||
	sctp_v4_del_protocol();
 | 
						sctp_v4_del_protocol();
 | 
				
			||||||
err_add_protocol:
 | 
					err_add_protocol:
 | 
				
			||||||
 | 
						unregister_pernet_subsys(&sctp_net_ops);
 | 
				
			||||||
 | 
					err_register_pernet_subsys:
 | 
				
			||||||
	inet_ctl_sock_destroy(sctp_ctl_sock);
 | 
						inet_ctl_sock_destroy(sctp_ctl_sock);
 | 
				
			||||||
err_ctl_sock_init:
 | 
					err_ctl_sock_init:
 | 
				
			||||||
	sctp_v6_protosw_exit();
 | 
						sctp_v6_protosw_exit();
 | 
				
			||||||
err_v6_protosw_init:
 | 
					err_v6_protosw_init:
 | 
				
			||||||
	sctp_v4_protosw_exit();
 | 
						sctp_v4_protosw_exit();
 | 
				
			||||||
err_protosw_init:
 | 
					err_protosw_init:
 | 
				
			||||||
	sctp_free_local_addr_list();
 | 
					 | 
				
			||||||
	sctp_v4_pf_exit();
 | 
						sctp_v4_pf_exit();
 | 
				
			||||||
	sctp_v6_pf_exit();
 | 
						sctp_v6_pf_exit();
 | 
				
			||||||
	sctp_sysctl_unregister();
 | 
						sctp_sysctl_unregister();
 | 
				
			||||||
| 
						 | 
					@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void)
 | 
				
			||||||
	/* Unregister with inet6/inet layers. */
 | 
						/* Unregister with inet6/inet layers. */
 | 
				
			||||||
	sctp_v6_del_protocol();
 | 
						sctp_v6_del_protocol();
 | 
				
			||||||
	sctp_v4_del_protocol();
 | 
						sctp_v4_del_protocol();
 | 
				
			||||||
	sctp_free_addr_wq();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Free the control endpoint.  */
 | 
						/* Free the control endpoint.  */
 | 
				
			||||||
	inet_ctl_sock_destroy(sctp_ctl_sock);
 | 
						inet_ctl_sock_destroy(sctp_ctl_sock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unregister_pernet_subsys(&sctp_net_ops);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Free protosw registrations */
 | 
						/* Free protosw registrations */
 | 
				
			||||||
	sctp_v6_protosw_exit();
 | 
						sctp_v6_protosw_exit();
 | 
				
			||||||
	sctp_v4_protosw_exit();
 | 
						sctp_v4_protosw_exit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Free the local address list.  */
 | 
					 | 
				
			||||||
	sctp_free_local_addr_list();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Unregister with socket layer. */
 | 
						/* Unregister with socket layer. */
 | 
				
			||||||
	sctp_v6_pf_exit();
 | 
						sctp_v6_pf_exit();
 | 
				
			||||||
	sctp_v4_pf_exit();
 | 
						sctp_v4_pf_exit();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3471,7 +3471,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
 | 
				
			||||||
		sp->do_auto_asconf = 0;
 | 
							sp->do_auto_asconf = 0;
 | 
				
			||||||
	} else if (val && !sp->do_auto_asconf) {
 | 
						} else if (val && !sp->do_auto_asconf) {
 | 
				
			||||||
		list_add_tail(&sp->auto_asconf_list,
 | 
							list_add_tail(&sp->auto_asconf_list,
 | 
				
			||||||
		    &sctp_auto_asconf_splist);
 | 
							    &sock_net(sk)->sctp.auto_asconf_splist);
 | 
				
			||||||
		sp->do_auto_asconf = 1;
 | 
							sp->do_auto_asconf = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						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);
 | 
						sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
 | 
				
			||||||
	if (sctp_default_auto_asconf) {
 | 
						if (sctp_default_auto_asconf) {
 | 
				
			||||||
		list_add_tail(&sp->auto_asconf_list,
 | 
							list_add_tail(&sp->auto_asconf_list,
 | 
				
			||||||
		    &sctp_auto_asconf_splist);
 | 
							    &sock_net(sk)->sctp.auto_asconf_splist);
 | 
				
			||||||
		sp->do_auto_asconf = 1;
 | 
							sp->do_auto_asconf = 1;
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		sp->do_auto_asconf = 0;
 | 
							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;
 | 
						union sctp_addr temp;
 | 
				
			||||||
	int cnt = 0;
 | 
						int cnt = 0;
 | 
				
			||||||
	int addrlen;
 | 
						int addrlen;
 | 
				
			||||||
 | 
						struct net *net = sock_net(sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						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)
 | 
							if (!addr->valid)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue