diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 45 | 
1 files changed, 25 insertions, 20 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ee88f2ea510..01c6364245b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -107,8 +107,6 @@ static void sctp_sock_migrate(struct sock *, struct sock *,  			      struct sctp_association *, sctp_socket_type_t);  static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; -extern struct kmem_cache *sctp_bucket_cachep; -  /* Get the sndbuf space available at the time on the association.  */  static inline int sctp_wspace(struct sctp_association *asoc)  { @@ -433,7 +431,7 @@ out:   *   * Only sctp_setsockopt_bindx() is supposed to call this function.   */ -int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) +static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)  {  	int cnt;  	int retval = 0; @@ -602,7 +600,7 @@ out:   *   * Only sctp_setsockopt_bindx() is supposed to call this function.   */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) +static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)  {  	struct sctp_sock *sp = sctp_sk(sk);  	struct sctp_endpoint *ep = sp->ep; @@ -977,7 +975,7 @@ static int __sctp_connect(struct sock* sk,  	int err = 0;  	int addrcnt = 0;  	int walk_size = 0; -	union sctp_addr *sa_addr; +	union sctp_addr *sa_addr = NULL;  	void *addr_buf;  	unsigned short port;  	unsigned int f_flags = 0; @@ -1011,7 +1009,10 @@ static int __sctp_connect(struct sock* sk,  			goto out_free;  		} -		err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len); +		/* Save current address so we can work with it */ +		memcpy(&to, sa_addr, af->sockaddr_len); + +		err = sctp_verify_addr(sk, &to, af->sockaddr_len);  		if (err)  			goto out_free; @@ -1021,12 +1022,11 @@ static int __sctp_connect(struct sock* sk,  		if (asoc && asoc->peer.port && asoc->peer.port != port)  			goto out_free; -		memcpy(&to, sa_addr, af->sockaddr_len);  		/* Check if there already is a matching association on the  		 * endpoint (other than the one created here).  		 */ -		asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport); +		asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);  		if (asoc2 && asoc2 != asoc) {  			if (asoc2->state >= SCTP_STATE_ESTABLISHED)  				err = -EISCONN; @@ -1039,7 +1039,7 @@ static int __sctp_connect(struct sock* sk,  		 * make sure that there is no peeled-off association matching  		 * the peer address even on another socket.  		 */ -		if (sctp_endpoint_is_peeled_off(ep, sa_addr)) { +		if (sctp_endpoint_is_peeled_off(ep, &to)) {  			err = -EADDRNOTAVAIL;  			goto out_free;  		} @@ -1070,7 +1070,7 @@ static int __sctp_connect(struct sock* sk,  				}  			} -			scope = sctp_scope(sa_addr); +			scope = sctp_scope(&to);  			asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);  			if (!asoc) {  				err = -ENOMEM; @@ -1079,7 +1079,7 @@ static int __sctp_connect(struct sock* sk,  		}  		/* Prime the peer's transport structures.  */ -		transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL, +		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,  						SCTP_UNKNOWN);  		if (!transport) {  			err = -ENOMEM; @@ -1103,8 +1103,8 @@ static int __sctp_connect(struct sock* sk,  	/* Initialize sk's dport and daddr for getpeername() */  	inet_sk(sk)->dport = htons(asoc->peer.port); -	af = sctp_get_af_specific(to.sa.sa_family); -	af->to_sk_daddr(&to, sk); +	af = sctp_get_af_specific(sa_addr->sa.sa_family); +	af->to_sk_daddr(sa_addr, sk);  	sk->sk_err = 0;  	/* in-kernel sockets don't generally have a file allocated to them @@ -1531,7 +1531,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,  			goto out_unlock;  		}  		if (sinfo_flags & SCTP_ABORT) { -			struct sctp_chunk *chunk;  			chunk = sctp_make_abort_user(asoc, msg, msg_len);  			if (!chunk) { @@ -4353,7 +4352,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,  						space_left, &bytes_copied);  			if (cnt < 0) {  				err = cnt; -				goto error; +				goto error_lock;  			}  			goto copy_getaddrs;  		} @@ -4367,7 +4366,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,  		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;  		if (space_left < addrlen) {  			err =  -ENOMEM; /*fixme: right error?*/ -			goto error; +			goto error_lock;  		}  		memcpy(buf, &temp, addrlen);  		buf += addrlen; @@ -4381,15 +4380,21 @@ copy_getaddrs:  	if (copy_to_user(to, addrs, bytes_copied)) {  		err = -EFAULT; -		goto error; +		goto out;  	}  	if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) {  		err = -EFAULT; -		goto error; +		goto out;  	}  	if (put_user(bytes_copied, optlen))  		err = -EFAULT; -error: + +	goto out; + +error_lock: +	sctp_read_unlock(addr_lock); + +out:  	kfree(addrs);  	return err;  } @@ -5964,7 +5969,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo)  	return err;  } -void sctp_wait_for_close(struct sock *sk, long timeout) +static void sctp_wait_for_close(struct sock *sk, long timeout)  {  	DEFINE_WAIT(wait);  | 
