mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-06 06:37:59 +00:00
sctp: Support the new specification of sctp_connectx()
The specification of sctp_connectx() has been changed to return an association id. We've added a new socket option that will return the association id as the return value from the setsockopt() call. The library that implements sctp_connectx() interface will implement both socket options. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d364d9276b
commit
88a0a948e7
2 changed files with 63 additions and 13 deletions
|
@ -137,12 +137,14 @@ enum sctp_optname {
|
||||||
#define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD
|
#define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD
|
||||||
SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */
|
SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */
|
||||||
#define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD
|
#define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD
|
||||||
SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
|
SCTP_SOCKOPT_CONNECTX_OLD, /* CONNECTX old requests. */
|
||||||
#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
|
#define SCTP_SOCKOPT_CONNECTX_OLD SCTP_SOCKOPT_CONNECTX_OLD
|
||||||
SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */
|
SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */
|
||||||
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
|
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
|
||||||
SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */
|
SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */
|
||||||
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
|
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
|
||||||
|
SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
|
||||||
|
#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -956,7 +956,8 @@ out:
|
||||||
*/
|
*/
|
||||||
static int __sctp_connect(struct sock* sk,
|
static int __sctp_connect(struct sock* sk,
|
||||||
struct sockaddr *kaddrs,
|
struct sockaddr *kaddrs,
|
||||||
int addrs_size)
|
int addrs_size,
|
||||||
|
sctp_assoc_t *assoc_id)
|
||||||
{
|
{
|
||||||
struct sctp_sock *sp;
|
struct sctp_sock *sp;
|
||||||
struct sctp_endpoint *ep;
|
struct sctp_endpoint *ep;
|
||||||
|
@ -1111,6 +1112,8 @@ static int __sctp_connect(struct sock* sk,
|
||||||
timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
|
timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
|
||||||
|
|
||||||
err = sctp_wait_for_connect(asoc, &timeo);
|
err = sctp_wait_for_connect(asoc, &timeo);
|
||||||
|
if (!err && assoc_id)
|
||||||
|
*assoc_id = asoc->assoc_id;
|
||||||
|
|
||||||
/* Don't free association on exit. */
|
/* Don't free association on exit. */
|
||||||
asoc = NULL;
|
asoc = NULL;
|
||||||
|
@ -1128,7 +1131,8 @@ out_free:
|
||||||
/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
|
/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
|
||||||
*
|
*
|
||||||
* API 8.9
|
* API 8.9
|
||||||
* int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
|
* int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt,
|
||||||
|
* sctp_assoc_t *asoc);
|
||||||
*
|
*
|
||||||
* If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
|
* If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
|
||||||
* If the sd is an IPv6 socket, the addresses passed can either be IPv4
|
* If the sd is an IPv6 socket, the addresses passed can either be IPv4
|
||||||
|
@ -1144,8 +1148,10 @@ out_free:
|
||||||
* representation is termed a "packed array" of addresses). The caller
|
* representation is termed a "packed array" of addresses). The caller
|
||||||
* specifies the number of addresses in the array with addrcnt.
|
* specifies the number of addresses in the array with addrcnt.
|
||||||
*
|
*
|
||||||
* On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
|
* On success, sctp_connectx() returns 0. It also sets the assoc_id to
|
||||||
* -1, and sets errno to the appropriate error code.
|
* the association id of the new association. On failure, sctp_connectx()
|
||||||
|
* returns -1, and sets errno to the appropriate error code. The assoc_id
|
||||||
|
* is not touched by the kernel.
|
||||||
*
|
*
|
||||||
* For SCTP, the port given in each socket address must be the same, or
|
* For SCTP, the port given in each socket address must be the same, or
|
||||||
* sctp_connectx() will fail, setting errno to EINVAL.
|
* sctp_connectx() will fail, setting errno to EINVAL.
|
||||||
|
@ -1182,11 +1188,12 @@ out_free:
|
||||||
* addrs The pointer to the addresses in user land
|
* addrs The pointer to the addresses in user land
|
||||||
* addrssize Size of the addrs buffer
|
* addrssize Size of the addrs buffer
|
||||||
*
|
*
|
||||||
* Returns 0 if ok, <0 errno code on error.
|
* Returns >=0 if ok, <0 errno code on error.
|
||||||
*/
|
*/
|
||||||
SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
|
SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk,
|
||||||
struct sockaddr __user *addrs,
|
struct sockaddr __user *addrs,
|
||||||
int addrs_size)
|
int addrs_size,
|
||||||
|
sctp_assoc_t *assoc_id)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
struct sockaddr *kaddrs;
|
struct sockaddr *kaddrs;
|
||||||
|
@ -1209,13 +1216,46 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
|
||||||
if (__copy_from_user(kaddrs, addrs, addrs_size)) {
|
if (__copy_from_user(kaddrs, addrs, addrs_size)) {
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
err = __sctp_connect(sk, kaddrs, addrs_size);
|
err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(kaddrs);
|
kfree(kaddrs);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an older interface. It's kept for backward compatibility
|
||||||
|
* to the option that doesn't provide association id.
|
||||||
|
*/
|
||||||
|
SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk,
|
||||||
|
struct sockaddr __user *addrs,
|
||||||
|
int addrs_size)
|
||||||
|
{
|
||||||
|
return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New interface for the API. The since the API is done with a socket
|
||||||
|
* option, to make it simple we feed back the association id is as a return
|
||||||
|
* indication to the call. Error is always negative and association id is
|
||||||
|
* always positive.
|
||||||
|
*/
|
||||||
|
SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
|
||||||
|
struct sockaddr __user *addrs,
|
||||||
|
int addrs_size)
|
||||||
|
{
|
||||||
|
sctp_assoc_t assoc_id = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
else
|
||||||
|
return assoc_id;
|
||||||
|
}
|
||||||
|
|
||||||
/* API 3.1.4 close() - UDP Style Syntax
|
/* API 3.1.4 close() - UDP Style Syntax
|
||||||
* Applications use close() to perform graceful shutdown (as described in
|
* Applications use close() to perform graceful shutdown (as described in
|
||||||
* Section 10.1 of [SCTP]) on ALL the associations currently represented
|
* Section 10.1 of [SCTP]) on ALL the associations currently represented
|
||||||
|
@ -3206,9 +3246,17 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
|
||||||
optlen, SCTP_BINDX_REM_ADDR);
|
optlen, SCTP_BINDX_REM_ADDR);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCTP_SOCKOPT_CONNECTX_OLD:
|
||||||
|
/* 'optlen' is the size of the addresses buffer. */
|
||||||
|
retval = sctp_setsockopt_connectx_old(sk,
|
||||||
|
(struct sockaddr __user *)optval,
|
||||||
|
optlen);
|
||||||
|
break;
|
||||||
|
|
||||||
case SCTP_SOCKOPT_CONNECTX:
|
case SCTP_SOCKOPT_CONNECTX:
|
||||||
/* 'optlen' is the size of the addresses buffer. */
|
/* 'optlen' is the size of the addresses buffer. */
|
||||||
retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
|
retval = sctp_setsockopt_connectx(sk,
|
||||||
|
(struct sockaddr __user *)optval,
|
||||||
optlen);
|
optlen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3336,7 +3384,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
|
||||||
/* Pass correct addr len to common routine (so it knows there
|
/* Pass correct addr len to common routine (so it knows there
|
||||||
* is only one address being passed.
|
* is only one address being passed.
|
||||||
*/
|
*/
|
||||||
err = __sctp_connect(sk, addr, af->sockaddr_len);
|
err = __sctp_connect(sk, addr, af->sockaddr_len, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctp_release_sock(sk);
|
sctp_release_sock(sk);
|
||||||
|
|
Loading…
Add table
Reference in a new issue