summaryrefslogtreecommitdiffstats
path: root/net/sctp/associola.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r--net/sctp/associola.c64
1 files changed, 28 insertions, 36 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index f4b23043b61..525864bf4f0 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -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)
-{
- struct sctp_transport *t;
-
- /* Use the retran path. If the last INIT 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)
+/* 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)
{
- /* 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
+ /* 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->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;