diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2007-09-26 01:41:56 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:52:37 -0400 |
commit | e155d7692290f7bc539ccb8ebc3450ec964e53fd (patch) | |
tree | ceca4fe0902c5efc8fb0936ec40d9482907d5d3a /net/dccp/input.c | |
parent | cbe1f5f88af454303a9c1a0624209269430d49fe (diff) |
[DCCP]: Fix Reset/Sync-Flood Bug
This updates sequence number checking with regard to RFC 4340, 7.5.4.
Missing in the code was an exception for sequence-invalid Reset packets,
which get a Sync acknowledging GSR, instead of (as usual) P.seqno.
This can lead to an oscillating ping-pong flood of Reset packets.
In fact, it has been observed on the wire as follows:
1. client establishes connection to server;
2. before server can write to client, client crashes without notifying
the server (NB: now no longer possible due to ABORT function);
3. server sends DCCP-Data packet (has no ackno);
4. client generates Reset "No Connection", seqno=0, increments seqno;
5. server replies with Sync, using ackno = P.seqno;
6. client generates Reset "No Connection" with seqno = ackno + 1;
7. goto (5).
The difference is that now in (5) the server uses GSR. This causes the
Reset sent by the client in (6) to become sequence-valid, so that in (7)
the vicious circle is broken; the Reset is then enqueued and causes the
socket to enter TIMEWAIT state.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/input.c')
-rw-r--r-- | net/dccp/input.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c index 6276b23fc204..cde0e704dfce 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -102,9 +102,6 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) | |||
102 | * Update S.GSR, S.SWL, S.SWH | 102 | * Update S.GSR, S.SWL, S.SWH |
103 | * If P.type != Sync, | 103 | * If P.type != Sync, |
104 | * Update S.GAR | 104 | * Update S.GAR |
105 | * Otherwise, | ||
106 | * Send Sync packet acknowledging P.seqno | ||
107 | * Drop packet and return | ||
108 | */ | 105 | */ |
109 | lswl = dp->dccps_swl; | 106 | lswl = dp->dccps_swl; |
110 | lawl = dp->dccps_awl; | 107 | lawl = dp->dccps_awl; |
@@ -135,6 +132,17 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) | |||
135 | : "exists", | 132 | : "exists", |
136 | (unsigned long long) lawl, (unsigned long long) ackno, | 133 | (unsigned long long) lawl, (unsigned long long) ackno, |
137 | (unsigned long long) dp->dccps_awh); | 134 | (unsigned long long) dp->dccps_awh); |
135 | /* | ||
136 | * Step 6: Check sequence numbers | ||
137 | * Otherwise, | ||
138 | * If P.type == Reset, | ||
139 | * Send Sync packet acknowledging S.GSR | ||
140 | * Otherwise, | ||
141 | * Send Sync packet acknowledging P.seqno | ||
142 | * Drop packet and return | ||
143 | */ | ||
144 | if (dh->dccph_type == DCCP_PKT_RESET) | ||
145 | seqno = dp->dccps_gsr; | ||
138 | dccp_send_sync(sk, seqno, DCCP_PKT_SYNC); | 146 | dccp_send_sync(sk, seqno, DCCP_PKT_SYNC); |
139 | return -1; | 147 | return -1; |
140 | } | 148 | } |