diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-05-04 16:55:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-05-04 16:55:27 -0400 |
commit | 07d939677166cc4f000c767196872a9becc2697b (patch) | |
tree | bef3d3c75ac3dd56813adbc63281feb4195a5b47 /net/sctp/sm_make_chunk.c | |
parent | 827bf12236fbafc02bc899aec1b37c342c8cf4e5 (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/sm_make_chunk.c')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 15 |
1 files changed, 2 insertions, 13 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index be783a3761c4..8d18f570c2e6 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1939,7 +1939,6 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1939 | * association. | 1939 | * association. |
1940 | */ | 1940 | */ |
1941 | if (!asoc->temp) { | 1941 | if (!asoc->temp) { |
1942 | int assoc_id; | ||
1943 | int error; | 1942 | int error; |
1944 | 1943 | ||
1945 | asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, | 1944 | asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, |
@@ -1947,19 +1946,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1947 | if (!asoc->ssnmap) | 1946 | if (!asoc->ssnmap) |
1948 | goto clean_up; | 1947 | goto clean_up; |
1949 | 1948 | ||
1950 | retry: | 1949 | error = sctp_assoc_set_id(asoc, gfp); |
1951 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | 1950 | if (error) |
1952 | goto clean_up; | 1951 | goto clean_up; |
1953 | spin_lock_bh(&sctp_assocs_id_lock); | ||
1954 | error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, 1, | ||
1955 | &assoc_id); | ||
1956 | spin_unlock_bh(&sctp_assocs_id_lock); | ||
1957 | if (error == -EAGAIN) | ||
1958 | goto retry; | ||
1959 | else if (error) | ||
1960 | goto clean_up; | ||
1961 | |||
1962 | asoc->assoc_id = (sctp_assoc_t) assoc_id; | ||
1963 | } | 1952 | } |
1964 | 1953 | ||
1965 | /* ADDIP Section 4.1 ASCONF Chunk Procedures | 1954 | /* ADDIP Section 4.1 ASCONF Chunk Procedures |