aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/associola.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-05-04 16:55:27 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-04 16:55:27 -0400
commit07d939677166cc4f000c767196872a9becc2697b (patch)
treebef3d3c75ac3dd56813adbc63281feb4195a5b47 /net/sctp/associola.c
parent827bf12236fbafc02bc899aec1b37c342c8cf4e5 (diff)
[SCTP]: Set assoc_id correctly during INIT collision.
During the INIT/COOKIE-ACK collision cases, it's possible to get into a situation where the association id is not yet set at the time of the user event generation. As a result, user events have an association id set to 0 which will confuse applications. This happens if we hit case B of duplicate cookie processing. In the particular example found and provided by Oscar Isaula <Oscar.Isaula@motorola.com>, flow looks like this: A B ---- INIT-------> (lost) <---------INIT------ ---- INIT-ACK---> <------ Cookie ECHO When the Cookie Echo is received, we end up trying to update the association that was created on A as a result of the (lost) INIT, but that association doesn't have the ID set yet. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r--net/sctp/associola.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index db73ef97485a..df94e3cdfba3 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1103,6 +1103,13 @@ void sctp_assoc_update(struct sctp_association *asoc,
1103 asoc->ssnmap = new->ssnmap; 1103 asoc->ssnmap = new->ssnmap;
1104 new->ssnmap = NULL; 1104 new->ssnmap = NULL;
1105 } 1105 }
1106
1107 if (!asoc->assoc_id) {
1108 /* get a new association id since we don't have one
1109 * yet.
1110 */
1111 sctp_assoc_set_id(asoc, GFP_ATOMIC);
1112 }
1106 } 1113 }
1107} 1114}
1108 1115
@@ -1375,3 +1382,25 @@ out:
1375 sctp_read_unlock(&asoc->base.addr_lock); 1382 sctp_read_unlock(&asoc->base.addr_lock);
1376 return found; 1383 return found;
1377} 1384}
1385
1386/* Set an association id for a given association */
1387int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
1388{
1389 int assoc_id;
1390 int error = 0;
1391retry:
1392 if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
1393 return -ENOMEM;
1394
1395 spin_lock_bh(&sctp_assocs_id_lock);
1396 error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
1397 1, &assoc_id);
1398 spin_unlock_bh(&sctp_assocs_id_lock);
1399 if (error == -EAGAIN)
1400 goto retry;
1401 else if (error)
1402 return error;
1403
1404 asoc->assoc_id = (sctp_assoc_t) assoc_id;
1405 return error;
1406}