aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorAndrea Bittau <a.bittau@cs.ucl.ac.uk>2006-01-03 17:25:17 -0500
committerDavid S. Miller <davem@davemloft.net>2006-01-03 17:25:17 -0500
commit709dd3aaf5304993083c2297c73f5531c36fba5a (patch)
tree8e6929b88040fb9acb92c3bfe1c45f210ad8e659 /net/dccp
parent5062430c5cc526655e3d10c670fc9c263656f66c (diff)
[DCCP]: Do not process a packet twice when it's not in state DCCP_OPEN.
When packets are received, the connection is either in DCCP_OPEN [fast-path] or it isn't. If it's not [e.g. DCCP_PARTOPEN] upper layers will perform sanity checks and parse options. If it is in DCCP_OPEN, dccp_rcv_established() will do it. It is important not to re-parse options in dccp_rcv_established() when it is not called from the fast-path. Else, fore example, the ack vector will be added twice and the CCID will see the packet twice. The solution is to always enfore sanity checks from the upper layers. When packets arrive in the fast-path, sanity checks will be performed before calling dccp_rcv_established(). Note(acme): I rewrote the patch to achieve the same result but keeping dccp_rcv_established with the previous semantics and having it split into __dccp_rcv_established, that doesn't does do any sanity check, code in state != DCCP_OPEN use this lighter version as they already do the sanity checks. Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk> Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/input.c56
1 files changed, 34 insertions, 22 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 55e921bdd131..5e312b04a7db 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -151,29 +151,12 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
151 return 0; 151 return 0;
152} 152}
153 153
154int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 154static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
155 const struct dccp_hdr *dh, const unsigned len) 155 const struct dccp_hdr *dh,
156 const unsigned len)
156{ 157{
157 struct dccp_sock *dp = dccp_sk(sk); 158 struct dccp_sock *dp = dccp_sk(sk);
158 159
159 if (dccp_check_seqno(sk, skb))
160 goto discard;
161
162 if (dccp_parse_options(sk, skb))
163 goto discard;
164
165 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
166 dccp_event_ack_recv(sk, skb);
167
168 if (dp->dccps_options.dccpo_send_ack_vector &&
169 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
170 DCCP_SKB_CB(skb)->dccpd_seq,
171 DCCP_ACKVEC_STATE_RECEIVED))
172 goto discard;
173
174 ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
175 ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
176
177 switch (dccp_hdr(skb)->dccph_type) { 160 switch (dccp_hdr(skb)->dccph_type) {
178 case DCCP_PKT_DATAACK: 161 case DCCP_PKT_DATAACK:
179 case DCCP_PKT_DATA: 162 case DCCP_PKT_DATA:
@@ -250,6 +233,35 @@ discard:
250 return 0; 233 return 0;
251} 234}
252 235
236int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
237 const struct dccp_hdr *dh, const unsigned len)
238{
239 struct dccp_sock *dp = dccp_sk(sk);
240
241 if (dccp_check_seqno(sk, skb))
242 goto discard;
243
244 if (dccp_parse_options(sk, skb))
245 goto discard;
246
247 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
248 dccp_event_ack_recv(sk, skb);
249
250 if (dp->dccps_options.dccpo_send_ack_vector &&
251 dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
252 DCCP_SKB_CB(skb)->dccpd_seq,
253 DCCP_ACKVEC_STATE_RECEIVED))
254 goto discard;
255
256 ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
257 ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
258
259 return __dccp_rcv_established(sk, skb, dh, len);
260discard:
261 __kfree_skb(skb);
262 return 0;
263}
264
253EXPORT_SYMBOL_GPL(dccp_rcv_established); 265EXPORT_SYMBOL_GPL(dccp_rcv_established);
254 266
255static int dccp_rcv_request_sent_state_process(struct sock *sk, 267static int dccp_rcv_request_sent_state_process(struct sock *sk,
@@ -400,9 +412,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
400 412
401 if (dh->dccph_type == DCCP_PKT_DATAACK || 413 if (dh->dccph_type == DCCP_PKT_DATAACK ||
402 dh->dccph_type == DCCP_PKT_DATA) { 414 dh->dccph_type == DCCP_PKT_DATA) {
403 dccp_rcv_established(sk, skb, dh, len); 415 __dccp_rcv_established(sk, skb, dh, len);
404 queued = 1; /* packet was queued 416 queued = 1; /* packet was queued
405 (by dccp_rcv_established) */ 417 (by __dccp_rcv_established) */
406 } 418 }
407 break; 419 break;
408 } 420 }