diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 40 | 
1 files changed, 25 insertions, 15 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c8d05758661..3a95fcb17a9 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1080,6 +1080,13 @@ static int __sctp_connect(struct sock* sk,  				err = -ENOMEM;  				goto out_free;  			} + +			err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, +							      GFP_KERNEL); +			if (err < 0) { +				goto out_free; +			} +  		}  		/* Prime the peer's transport structures.  */ @@ -1095,11 +1102,6 @@ static int __sctp_connect(struct sock* sk,  		walk_size += af->sockaddr_len;  	} -	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); -	if (err < 0) { -		goto out_free; -	} -  	/* In case the user of sctp_connectx() wants an association  	 * id back, assign one now.  	 */ @@ -1274,22 +1276,30 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,  }  /* - * New (hopefully final) interface for the API.  The option buffer is used - * both for the returned association id and the addresses. + * New (hopefully final) interface for the API. + * We use the sctp_getaddrs_old structure so that use-space library + * can avoid any unnecessary allocations.   The only defferent part + * is that we store the actual length of the address buffer into the + * addrs_num structure member.  That way we can re-use the existing + * code.   */  SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len,  					char __user *optval,  					int __user *optlen)  { +	struct sctp_getaddrs_old param;  	sctp_assoc_t assoc_id = 0;  	int err = 0; -	if (len < sizeof(assoc_id)) +	if (len < sizeof(param))  		return -EINVAL; +	if (copy_from_user(¶m, optval, sizeof(param))) +		return -EFAULT; +  	err = __sctp_setsockopt_connectx(sk, -			(struct sockaddr __user *)(optval + sizeof(assoc_id)), -			len - sizeof(assoc_id), &assoc_id); +			(struct sockaddr __user *)param.addrs, +			param.addr_num, &assoc_id);  	if (err == 0 || err == -EINPROGRESS) {  		if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) @@ -1689,6 +1699,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,  			goto out_unlock;  		}  		asoc = new_asoc; +		err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); +		if (err < 0) { +			err = -ENOMEM; +			goto out_free; +		}  		/* If the SCTP_INIT ancillary data is specified, set all  		 * the association init values accordingly. @@ -1718,11 +1733,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,  			err = -ENOMEM;  			goto out_free;  		} -		err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); -		if (err < 0) { -			err = -ENOMEM; -			goto out_free; -		}  	}  	/* ASSERT: we have a valid association at this point.  */  |