Merge branch 'net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vxy/lksctp-dev
This commit is contained in:
commit
a8c617eae4
@ -487,17 +487,17 @@ typedef enum {
|
||||
*
|
||||
* Value Cause Code
|
||||
* --------- ----------------
|
||||
* 0x0100 Request to Delete Last Remaining IP Address.
|
||||
* 0x0101 Operation Refused Due to Resource Shortage.
|
||||
* 0x0102 Request to Delete Source IP Address.
|
||||
* 0x0103 Association Aborted due to illegal ASCONF-ACK
|
||||
* 0x0104 Request refused - no authorization.
|
||||
* 0x00A0 Request to Delete Last Remaining IP Address.
|
||||
* 0x00A1 Operation Refused Due to Resource Shortage.
|
||||
* 0x00A2 Request to Delete Source IP Address.
|
||||
* 0x00A3 Association Aborted due to illegal ASCONF-ACK
|
||||
* 0x00A4 Request refused - no authorization.
|
||||
*/
|
||||
SCTP_ERROR_DEL_LAST_IP = cpu_to_be16(0x0100),
|
||||
SCTP_ERROR_RSRC_LOW = cpu_to_be16(0x0101),
|
||||
SCTP_ERROR_DEL_SRC_IP = cpu_to_be16(0x0102),
|
||||
SCTP_ERROR_ASCONF_ACK = cpu_to_be16(0x0103),
|
||||
SCTP_ERROR_REQ_REFUSED = cpu_to_be16(0x0104),
|
||||
SCTP_ERROR_DEL_LAST_IP = cpu_to_be16(0x00A0),
|
||||
SCTP_ERROR_RSRC_LOW = cpu_to_be16(0x00A1),
|
||||
SCTP_ERROR_DEL_SRC_IP = cpu_to_be16(0x00A2),
|
||||
SCTP_ERROR_ASCONF_ACK = cpu_to_be16(0x00A3),
|
||||
SCTP_ERROR_REQ_REFUSED = cpu_to_be16(0x00A4),
|
||||
|
||||
/* AUTH Section 4. New Error Cause
|
||||
*
|
||||
|
@ -1939,10 +1939,8 @@ void sctp_association_free(struct sctp_association *);
|
||||
void sctp_association_put(struct sctp_association *);
|
||||
void sctp_association_hold(struct sctp_association *);
|
||||
|
||||
struct sctp_transport *sctp_assoc_choose_init_transport(
|
||||
struct sctp_association *);
|
||||
struct sctp_transport *sctp_assoc_choose_shutdown_transport(
|
||||
struct sctp_association *);
|
||||
struct sctp_transport *sctp_assoc_choose_alter_transport(
|
||||
struct sctp_association *, struct sctp_transport *);
|
||||
void sctp_assoc_update_retran_path(struct sctp_association *);
|
||||
struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *,
|
||||
const union sctp_addr *);
|
||||
|
@ -147,6 +147,8 @@ enum sctp_optname {
|
||||
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
|
||||
SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
|
||||
#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
|
||||
SCTP_SOCKOPT_CONNECTX3, /* CONNECTX requests. (new implementation) */
|
||||
#define SCTP_SOCKOPT_CONNECTX3 SCTP_SOCKOPT_CONNECTX3
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -293,7 +293,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
||||
* told otherwise.
|
||||
*/
|
||||
asoc->peer.ipv4_address = 1;
|
||||
asoc->peer.ipv6_address = 1;
|
||||
if (asoc->base.sk->sk_family == PF_INET6)
|
||||
asoc->peer.ipv6_address = 1;
|
||||
INIT_LIST_HEAD(&asoc->asocs);
|
||||
|
||||
asoc->autoclose = sp->autoclose;
|
||||
@ -566,6 +567,21 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
|
||||
if (asoc->init_last_sent_to == peer)
|
||||
asoc->init_last_sent_to = NULL;
|
||||
|
||||
/* If we remove the transport an SHUTDOWN was last sent to, set it
|
||||
* to NULL. Combined with the update of the retran path above, this
|
||||
* will cause the next SHUTDOWN to be sent to the next available
|
||||
* transport, maintaining the cycle.
|
||||
*/
|
||||
if (asoc->shutdown_last_sent_to == peer)
|
||||
asoc->shutdown_last_sent_to = NULL;
|
||||
|
||||
/* If we remove the transport an ASCONF was last sent to, set it to
|
||||
* NULL.
|
||||
*/
|
||||
if (asoc->addip_last_asconf &&
|
||||
asoc->addip_last_asconf->transport == peer)
|
||||
asoc->addip_last_asconf->transport = NULL;
|
||||
|
||||
asoc->peer.transport_count--;
|
||||
|
||||
sctp_transport_free(peer);
|
||||
@ -1268,49 +1284,21 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
|
||||
ntohs(t->ipaddr.v4.sin_port));
|
||||
}
|
||||
|
||||
/* Choose the transport for sending a INIT packet. */
|
||||
struct sctp_transport *sctp_assoc_choose_init_transport(
|
||||
struct sctp_association *asoc)
|
||||
/* Choose the transport for sending retransmit packet. */
|
||||
struct sctp_transport *sctp_assoc_choose_alter_transport(
|
||||
struct sctp_association *asoc, struct sctp_transport *last_sent_to)
|
||||
{
|
||||
struct sctp_transport *t;
|
||||
|
||||
/* Use the retran path. If the last INIT was sent over the
|
||||
/* If this is the first time packet is sent, use the active path,
|
||||
* else use the retran path. If the last packet was sent over the
|
||||
* retran path, update the retran path and use it.
|
||||
*/
|
||||
if (!asoc->init_last_sent_to) {
|
||||
t = asoc->peer.active_path;
|
||||
} else {
|
||||
if (asoc->init_last_sent_to == asoc->peer.retran_path)
|
||||
sctp_assoc_update_retran_path(asoc);
|
||||
t = asoc->peer.retran_path;
|
||||
}
|
||||
|
||||
SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
|
||||
" %p addr: ",
|
||||
" port: %d\n",
|
||||
asoc,
|
||||
(&t->ipaddr),
|
||||
ntohs(t->ipaddr.v4.sin_port));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Choose the transport for sending a SHUTDOWN packet. */
|
||||
struct sctp_transport *sctp_assoc_choose_shutdown_transport(
|
||||
struct sctp_association *asoc)
|
||||
{
|
||||
/* If this is the first time SHUTDOWN is sent, use the active path,
|
||||
* else use the retran path. If the last SHUTDOWN was sent over the
|
||||
* retran path, update the retran path and use it.
|
||||
*/
|
||||
if (!asoc->shutdown_last_sent_to)
|
||||
if (!last_sent_to)
|
||||
return asoc->peer.active_path;
|
||||
else {
|
||||
if (asoc->shutdown_last_sent_to == asoc->peer.retran_path)
|
||||
if (last_sent_to == asoc->peer.retran_path)
|
||||
sctp_assoc_update_retran_path(asoc);
|
||||
return asoc->peer.retran_path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Update the association's pmtu and frag_point by going through all the
|
||||
@ -1482,6 +1470,10 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
|
||||
{
|
||||
int assoc_id;
|
||||
int error = 0;
|
||||
|
||||
/* If the id is already assigned, keep it. */
|
||||
if (asoc->assoc_id)
|
||||
return error;
|
||||
retry:
|
||||
if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
|
||||
return -ENOMEM;
|
||||
|
@ -2864,19 +2864,19 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
||||
switch (addr_param->v4.param_hdr.type) {
|
||||
case SCTP_PARAM_IPV6_ADDRESS:
|
||||
if (!asoc->peer.ipv6_address)
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
break;
|
||||
case SCTP_PARAM_IPV4_ADDRESS:
|
||||
if (!asoc->peer.ipv4_address)
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
break;
|
||||
default:
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
}
|
||||
|
||||
af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
|
||||
if (unlikely(!af))
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
|
||||
af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0);
|
||||
|
||||
@ -2886,7 +2886,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
||||
* make sure we check for that)
|
||||
*/
|
||||
if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb))
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
|
||||
switch (asconf_param->param_hdr.type) {
|
||||
case SCTP_PARAM_ADD_IP:
|
||||
@ -2954,12 +2954,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
||||
|
||||
peer = sctp_assoc_lookup_paddr(asoc, &addr);
|
||||
if (!peer)
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
|
||||
sctp_assoc_set_primary(asoc, peer);
|
||||
break;
|
||||
default:
|
||||
return SCTP_ERROR_INV_PARAM;
|
||||
return SCTP_ERROR_UNKNOWN_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3273,7 +3273,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
|
||||
retval = 1;
|
||||
break;
|
||||
|
||||
case SCTP_ERROR_INV_PARAM:
|
||||
case SCTP_ERROR_UNKNOWN_PARAM:
|
||||
/* Disable sending this type of asconf parameter in
|
||||
* future.
|
||||
*/
|
||||
|
@ -686,7 +686,8 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds,
|
||||
{
|
||||
struct sctp_transport *t;
|
||||
|
||||
t = sctp_assoc_choose_shutdown_transport(asoc);
|
||||
t = sctp_assoc_choose_alter_transport(asoc,
|
||||
asoc->shutdown_last_sent_to);
|
||||
asoc->shutdown_last_sent_to = t;
|
||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto;
|
||||
chunk->transport = t;
|
||||
@ -777,7 +778,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
|
||||
{
|
||||
struct sctp_transport *t;
|
||||
|
||||
t = asoc->peer.active_path;
|
||||
t = sctp_assoc_choose_alter_transport(asoc, chunk->transport);
|
||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto;
|
||||
chunk->transport = t;
|
||||
}
|
||||
@ -1379,7 +1380,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
|
||||
|
||||
case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
|
||||
chunk = cmd->obj.ptr;
|
||||
t = sctp_assoc_choose_init_transport(asoc);
|
||||
t = sctp_assoc_choose_alter_transport(asoc,
|
||||
asoc->init_last_sent_to);
|
||||
asoc->init_last_sent_to = t;
|
||||
chunk->transport = t;
|
||||
t->init_sent_count++;
|
||||
|
@ -5432,9 +5432,13 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
|
||||
if (!reply)
|
||||
goto nomem;
|
||||
|
||||
/* Do some failure management (Section 8.2). */
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE,
|
||||
SCTP_TRANSPORT(asoc->shutdown_last_sent_to));
|
||||
/* Do some failure management (Section 8.2).
|
||||
* If we remove the transport an SHUTDOWN was last sent to, don't
|
||||
* do failure management.
|
||||
*/
|
||||
if (asoc->shutdown_last_sent_to)
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE,
|
||||
SCTP_TRANSPORT(asoc->shutdown_last_sent_to));
|
||||
|
||||
/* Set the transport for the SHUTDOWN/ACK chunk and the timeout for
|
||||
* the T2-shutdown timer.
|
||||
@ -5471,7 +5475,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
|
||||
* detection on the appropriate destination address as defined in
|
||||
* RFC2960 [5] section 8.1 and 8.2.
|
||||
*/
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport));
|
||||
if (transport)
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE,
|
||||
SCTP_TRANSPORT(transport));
|
||||
|
||||
/* Reconfig T4 timer and transport. */
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk));
|
||||
|
@ -698,7 +698,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
|
||||
TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \
|
||||
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
|
||||
} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
|
||||
} /* TYPE_SCTP_PRIMITIVE_ASCONF */
|
||||
|
||||
/* The primary index for this table is the primitive type.
|
||||
* The secondary index for this table is the state.
|
||||
|
@ -1100,6 +1100,15 @@ static int __sctp_connect(struct sock* sk,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* In case the user of sctp_connectx() wants an association
|
||||
* id back, assign one now.
|
||||
*/
|
||||
if (assoc_id) {
|
||||
err = sctp_assoc_set_id(asoc, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
err = sctp_primitive_ASSOCIATE(asoc, NULL);
|
||||
if (err < 0) {
|
||||
goto out_free;
|
||||
@ -1120,7 +1129,7 @@ static int __sctp_connect(struct sock* sk,
|
||||
timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
|
||||
|
||||
err = sctp_wait_for_connect(asoc, &timeo);
|
||||
if (!err && assoc_id)
|
||||
if ((err == 0 || err == -EINPROGRESS) && assoc_id)
|
||||
*assoc_id = asoc->assoc_id;
|
||||
|
||||
/* Don't free association on exit. */
|
||||
@ -1264,6 +1273,34 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
|
||||
return assoc_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* New (hopefully final) interface for the API. The option buffer is used
|
||||
* both for the returned association id and the addresses.
|
||||
*/
|
||||
SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len,
|
||||
char __user *optval,
|
||||
int __user *optlen)
|
||||
{
|
||||
sctp_assoc_t assoc_id = 0;
|
||||
int err = 0;
|
||||
|
||||
if (len < sizeof(assoc_id))
|
||||
return -EINVAL;
|
||||
|
||||
err = __sctp_setsockopt_connectx(sk,
|
||||
(struct sockaddr __user *)(optval + sizeof(assoc_id)),
|
||||
len - sizeof(assoc_id), &assoc_id);
|
||||
|
||||
if (err == 0 || err == -EINPROGRESS) {
|
||||
if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
|
||||
return -EFAULT;
|
||||
if (put_user(sizeof(assoc_id), optlen))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* API 3.1.4 close() - UDP Style Syntax
|
||||
* Applications use close() to perform graceful shutdown (as described in
|
||||
* Section 10.1 of [SCTP]) on ALL the associations currently represented
|
||||
@ -5578,6 +5615,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
|
||||
retval = sctp_getsockopt_local_addrs(sk, len, optval,
|
||||
optlen);
|
||||
break;
|
||||
case SCTP_SOCKOPT_CONNECTX3:
|
||||
retval = sctp_getsockopt_connectx3(sk, len, optval, optlen);
|
||||
break;
|
||||
case SCTP_DEFAULT_SEND_PARAM:
|
||||
retval = sctp_getsockopt_default_send_param(sk, len,
|
||||
optval, optlen);
|
||||
|
@ -49,8 +49,8 @@ static int zero = 0;
|
||||
static int one = 1;
|
||||
static int timer_max = 86400000; /* ms in one day */
|
||||
static int int_max = INT_MAX;
|
||||
static long sack_timer_min = 1;
|
||||
static long sack_timer_max = 500;
|
||||
static int sack_timer_min = 1;
|
||||
static int sack_timer_max = 500;
|
||||
|
||||
extern int sysctl_sctp_mem[3];
|
||||
extern int sysctl_sctp_rmem[3];
|
||||
@ -223,7 +223,7 @@ static ctl_table sctp_table[] = {
|
||||
.ctl_name = NET_SCTP_SACK_TIMEOUT,
|
||||
.procname = "sack_timeout",
|
||||
.data = &sctp_sack_timeout,
|
||||
.maxlen = sizeof(long),
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
|
Loading…
Reference in New Issue
Block a user