*
* Returns 0 if ok, <0 errno code on error.
*/
-SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs,
+SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
+ struct sockaddr __user *addrs,
int addrs_size, int op)
{
struct sockaddr *kaddrs;
if (!asoc) {
SCTP_DEBUG_PRINTK("There is no association yet.\n");
+ if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
+
/* Check for invalid stream against the stream counts,
* either the default or the user specified stream counts.
*/
}
if (sinit->sinit_max_init_timeo) {
asoc->max_init_timeo =
- MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo);
+ msecs_to_jiffies(sinit->sinit_max_init_timeo);
}
}
* instead a error will be indicated to the user.
*/
static int sctp_setsockopt_disable_fragments(struct sock *sk,
- char *optval, int optlen)
+ char __user *optval, int optlen)
{
int val;
if (optlen < sizeof(int))
return -EINVAL;
- if (get_user(val, (int *)optval))
+ if (get_user(val, (int __user *)optval))
return -EFAULT;
sctp_sk(sk)->disable_fragments = (val == 0) ? 0 : 1;
return 0;
}
-static int sctp_setsockopt_events(struct sock *sk, char *optval,
+static int sctp_setsockopt_events(struct sock *sk, char __user *optval,
int optlen)
{
if (optlen != sizeof(struct sctp_event_subscribe))
* integer defining the number of seconds of idle time before an
* association is closed.
*/
-static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
+static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
int optlen)
{
struct sctp_opt *sp = sctp_sk(sk);
* considered unreachable.
*/
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
- char *optval, int optlen)
+ char __user *optval, int optlen)
{
struct sctp_paddrparams params;
struct sctp_transport *trans;
if (params.spp_hbinterval) {
trans->hb_allowed = 1;
trans->hb_interval =
- MSECS_TO_JIFFIES(params.spp_hbinterval);
+ msecs_to_jiffies(params.spp_hbinterval);
} else
trans->hb_allowed = 0;
}
* by the change). With TCP-style sockets, this option is inherited by
* sockets derived from a listener socket.
*/
-static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen)
+static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, int optlen)
{
struct sctp_initmsg sinit;
struct sctp_opt *sp = sctp_sk(sk);
* to this call if the caller is using the UDP model.
*/
static int sctp_setsockopt_default_send_param(struct sock *sk,
- char *optval, int optlen)
+ char __user *optval, int optlen)
{
struct sctp_sndrcvinfo info;
struct sctp_association *asoc;
* the association primary. The enclosed address must be one of the
* association peer's addresses.
*/
-static int sctp_setsockopt_primary_addr(struct sock *sk, char *optval,
+static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval,
int optlen)
{
struct sctp_prim prim;
* introduced, at the cost of more packets in the network. Expects an
* integer boolean flag.
*/
-static int sctp_setsockopt_nodelay(struct sock *sk, char *optval,
+static int sctp_setsockopt_nodelay(struct sock *sk, char __user *optval,
int optlen)
{
int val;
if (optlen < sizeof(int))
return -EINVAL;
- if (get_user(val, (int *)optval))
+ if (get_user(val, (int __user *)optval))
return -EFAULT;
sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1;
* be changed.
*
*/
-static int sctp_setsockopt_rtoinfo(struct sock *sk, char *optval, int optlen) {
+static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, int optlen) {
struct sctp_rtoinfo rtoinfo;
struct sctp_association *asoc;
if (asoc) {
if (rtoinfo.srto_initial != 0)
asoc->rto_initial =
- MSECS_TO_JIFFIES(rtoinfo.srto_initial);
+ msecs_to_jiffies(rtoinfo.srto_initial);
if (rtoinfo.srto_max != 0)
- asoc->rto_max = MSECS_TO_JIFFIES(rtoinfo.srto_max);
+ asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
if (rtoinfo.srto_min != 0)
- asoc->rto_min = MSECS_TO_JIFFIES(rtoinfo.srto_min);
+ asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);
} else {
/* If there is no association or the association-id = 0
* set the values to the endpoint.
* See [SCTP] for more information.
*
*/
-static int sctp_setsockopt_associnfo(struct sock *sk, char *optval, int optlen)
+static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int optlen)
{
struct sctp_assocparams assocparams;
* addresses and a user will receive both PF_INET6 and PF_INET type
* addresses on the socket.
*/
-static int sctp_setsockopt_mappedv4(struct sock *sk, char *optval, int optlen)
+static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int optlen)
{
int val;
struct sctp_opt *sp = sctp_sk(sk);
if (optlen < sizeof(int))
return -EINVAL;
- if (get_user(val, (int *)optval))
+ if (get_user(val, (int __user *)optval))
return -EFAULT;
if (val)
sp->v4mapped = 1;
* PMTU of the underlying association is smaller than the value set by
* the user.
*/
-static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen)
+static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen)
{
struct sctp_association *asoc;
struct list_head *pos;
if (optlen < sizeof(int))
return -EINVAL;
- if (get_user(val, (int *)optval))
+ if (get_user(val, (int __user *)optval))
return -EFAULT;
if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
return -EINVAL;
* locally bound addresses. The following structure is used to make a
* set primary request:
*/
-static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
+static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval,
int optlen)
{
struct sctp_opt *sp;
*
* The syntax is:
*
- * ret = getsockopt(int sd, int level, int optname, void *optval,
- * int *optlen);
- * ret = setsockopt(int sd, int level, int optname, const void *optval,
+ * ret = getsockopt(int sd, int level, int optname, void __user *optval,
+ * int __user *optlen);
+ * ret = setsockopt(int sd, int level, int optname, const void __user *optval,
* int optlen);
*
* sd - the socket descript.
* optlen - the size of the buffer.
*/
SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
- char *optval, int optlen)
+ char __user *optval, int optlen)
{
int retval = 0;
switch (optname) {
case SCTP_SOCKOPT_BINDX_ADD:
/* 'optlen' is the size of the addresses buffer. */
- retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval,
+ retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval,
optlen, SCTP_BINDX_ADD_ADDR);
break;
case SCTP_SOCKOPT_BINDX_REM:
/* 'optlen' is the size of the addresses buffer. */
- retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval,
+ retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval,
optlen, SCTP_BINDX_REM_ADDR);
break;
sp->initmsg.sinit_num_ostreams = sctp_max_outstreams;
sp->initmsg.sinit_max_instreams = sctp_max_instreams;
sp->initmsg.sinit_max_attempts = sctp_max_retrans_init;
- sp->initmsg.sinit_max_init_timeo = JIFFIES_TO_MSECS(sctp_rto_max);
+ sp->initmsg.sinit_max_init_timeo = jiffies_to_msecs(sctp_rto_max);
/* Initialize default RTO related parameters. These parameters can
* be modified for with the SCTP_RTOINFO socket option.
*/
- sp->rtoinfo.srto_initial = JIFFIES_TO_MSECS(sctp_rto_initial);
- sp->rtoinfo.srto_max = JIFFIES_TO_MSECS(sctp_rto_max);
- sp->rtoinfo.srto_min = JIFFIES_TO_MSECS(sctp_rto_min);
+ sp->rtoinfo.srto_initial = jiffies_to_msecs(sctp_rto_initial);
+ sp->rtoinfo.srto_max = jiffies_to_msecs(sctp_rto_max);
+ sp->rtoinfo.srto_min = jiffies_to_msecs(sctp_rto_min);
/* Initialize default association related parameters. These parameters
* can be modified with the SCTP_ASSOCINFO socket option.
sp->assocparams.sasoc_peer_rwnd = 0;
sp->assocparams.sasoc_local_rwnd = 0;
sp->assocparams.sasoc_cookie_life =
- JIFFIES_TO_MSECS(sctp_valid_cookie_life);
+ jiffies_to_msecs(sctp_valid_cookie_life);
/* Initialize default event subscriptions. By default, all the
* options are off.
/* Default Peer Address Parameters. These defaults can
* be modified via SCTP_PEER_ADDR_PARAMS
*/
- sp->paddrparam.spp_hbinterval = JIFFIES_TO_MSECS(sctp_hb_interval);
+ sp->paddrparam.spp_hbinterval = jiffies_to_msecs(sctp_hb_interval);
sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
/* If enabled no SCTP message fragmentation will be performed.
* number of unacked data chunks, and number of data chunks pending
* receipt. This information is read-only.
*/
-static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
- int *optlen)
+static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
{
struct sctp_status status;
struct sctp_association *asoc = NULL;
status.sstat_primary.spinfo_state = transport->active;
status.sstat_primary.spinfo_cwnd = transport->cwnd;
status.sstat_primary.spinfo_srtt = transport->srtt;
- status.sstat_primary.spinfo_rto = JIFFIES_TO_MSECS(transport->rto);
+ status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
status.sstat_primary.spinfo_mtu = transport->pmtu;
if (put_user(len, optlen)) {
* read-only.
*/
static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval,
+ int __user *optlen)
{
struct sctp_paddrinfo pinfo;
struct sctp_transport *transport;
pinfo.spinfo_state = transport->active;
pinfo.spinfo_cwnd = transport->cwnd;
pinfo.spinfo_srtt = transport->srtt;
- pinfo.spinfo_rto = JIFFIES_TO_MSECS(transport->rto);
+ pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
pinfo.spinfo_mtu = transport->pmtu;
if (put_user(len, optlen)) {
* instead a error will be indicated to the user.
*/
static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
int val;
* This socket option is used to specify various notifications and
* ancillary data the user wishes to receive.
*/
-static int sctp_getsockopt_events(struct sock *sk, int len, char *optval,
- int *optlen)
+static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
+ int __user *optlen)
{
if (len != sizeof(struct sctp_event_subscribe))
return -EINVAL;
* integer defining the number of seconds of idle time before an
* association is closed.
*/
-static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int *optlen)
+static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optval, int __user *optlen)
{
/* Applicable to UDP-style socket only */
if (sctp_style(sk, TCP))
return err;
}
-static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *optlen)
+static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval, int __user *optlen)
{
sctp_peeloff_arg_t peeloff;
struct socket *newsock;
* considered unreachable.
*/
static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
struct sctp_paddrparams params;
struct sctp_transport *trans;
if (len != sizeof(struct sctp_paddrparams))
return -EINVAL;
- if (copy_from_user(¶ms, optval, *optlen))
+ if (copy_from_user(¶ms, optval, len))
return -EFAULT;
trans = sctp_addr_id2transport(sk, ¶ms.spp_address,
if (!trans->hb_allowed)
params.spp_hbinterval = 0;
else
- params.spp_hbinterval = JIFFIES_TO_MSECS(trans->hb_interval);
+ params.spp_hbinterval = jiffies_to_msecs(trans->hb_interval);
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
* by the change). With TCP-style sockets, this option is inherited by
* sockets derived from a listener socket.
*/
-static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *optlen)
+static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen)
{
if (len != sizeof(struct sctp_initmsg))
return -EINVAL;
}
static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
sctp_assoc_t id;
struct sctp_association *asoc;
}
static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
struct sctp_association *asoc;
struct list_head *pos;
int cnt = 0;
struct sctp_getaddrs getaddrs;
struct sctp_transport *from;
- void *to;
+ void __user *to;
union sctp_addr temp;
struct sctp_opt *sp = sctp_sk(sk);
int addrlen;
if (!asoc)
return -EINVAL;
- to = (void *)getaddrs.addrs;
+ to = (void __user *)getaddrs.addrs;
list_for_each(pos, &asoc->peer.transport_addr_list) {
from = list_entry(pos, struct sctp_transport, transports);
memcpy(&temp, &from->ipaddr, sizeof(temp));
}
static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval,
+ int __user *optlen)
{
sctp_assoc_t id;
struct sctp_bind_addr *bp;
}
static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
struct sctp_bind_addr *bp;
struct sctp_association *asoc;
int cnt = 0;
struct sctp_getaddrs getaddrs;
struct sctp_sockaddr_entry *from;
- void *to;
+ void __user *to;
union sctp_addr temp;
struct sctp_opt *sp = sctp_sk(sk);
int addrlen;
bp = &asoc->base.bind_addr;
}
- to = (void *)getaddrs.addrs;
+ to = getaddrs.addrs;
list_for_each(pos, &bp->address_list) {
from = list_entry(pos,
struct sctp_sockaddr_entry,
* association peer's addresses.
*/
static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
struct sctp_prim prim;
struct sctp_association *asoc;
* For getsockopt, it get the default sctp_sndrcvinfo structure.
*/
static int sctp_getsockopt_default_send_param(struct sock *sk,
- int len, char *optval, int *optlen)
+ int len, char __user *optval,
+ int __user *optlen)
{
struct sctp_sndrcvinfo info;
struct sctp_association *asoc;
*/
static int sctp_getsockopt_nodelay(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
int val;
* be changed.
*
*/
-static int sctp_getsockopt_rtoinfo(struct sock *sk, int len, char *optval,
- int *optlen) {
+static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen) {
struct sctp_rtoinfo rtoinfo;
struct sctp_association *asoc;
/* Values corresponding to the specific association. */
if (asoc) {
- rtoinfo.srto_initial = JIFFIES_TO_MSECS(asoc->rto_initial);
- rtoinfo.srto_max = JIFFIES_TO_MSECS(asoc->rto_max);
- rtoinfo.srto_min = JIFFIES_TO_MSECS(asoc->rto_min);
+ rtoinfo.srto_initial = jiffies_to_msecs(asoc->rto_initial);
+ rtoinfo.srto_max = jiffies_to_msecs(asoc->rto_max);
+ rtoinfo.srto_min = jiffies_to_msecs(asoc->rto_min);
} else {
/* Values corresponding to the endpoint. */
struct sctp_opt *sp = sctp_sk(sk);
* See [SCTP] for more information.
*
*/
-static int sctp_getsockopt_associnfo(struct sock *sk, int len, char *optval,
- int *optlen)
+static int sctp_getsockopt_associnfo(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
{
struct sctp_assocparams assocparams;
* addresses on the socket.
*/
static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
int val;
struct sctp_opt *sp = sctp_sk(sk);
* the user.
*/
static int sctp_getsockopt_maxseg(struct sock *sk, int len,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
int val;
}
SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
int retval = 0;
int len;
return err;
do_error:
- err = -ECONNREFUSED;
+ if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
+ asoc->max_init_attempts)
+ err = -ETIMEDOUT;
+ else
+ err = -ECONNREFUSED;
goto out;
do_interrupted: