Skip to content

Commit

Permalink
[DCCP]: Do not process a packet twice when it's not in state DCCP_OPEN.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andrea Bittau authored and David S. Miller committed Jan 3, 2006
1 parent 5062430 commit 709dd3a
Showing 1 changed file with 34 additions and 22 deletions.
56 changes: 34 additions & 22 deletions net/dccp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,29 +151,12 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
return 0;
}

int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct dccp_hdr *dh, const unsigned len)
static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct dccp_hdr *dh,
const unsigned len)
{
struct dccp_sock *dp = dccp_sk(sk);

if (dccp_check_seqno(sk, skb))
goto discard;

if (dccp_parse_options(sk, skb))
goto discard;

if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_event_ack_recv(sk, skb);

if (dp->dccps_options.dccpo_send_ack_vector &&
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
DCCP_SKB_CB(skb)->dccpd_seq,
DCCP_ACKVEC_STATE_RECEIVED))
goto discard;

ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);

switch (dccp_hdr(skb)->dccph_type) {
case DCCP_PKT_DATAACK:
case DCCP_PKT_DATA:
Expand Down Expand Up @@ -250,6 +233,35 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
return 0;
}

int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct dccp_hdr *dh, const unsigned len)
{
struct dccp_sock *dp = dccp_sk(sk);

if (dccp_check_seqno(sk, skb))
goto discard;

if (dccp_parse_options(sk, skb))
goto discard;

if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_event_ack_recv(sk, skb);

if (dp->dccps_options.dccpo_send_ack_vector &&
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
DCCP_SKB_CB(skb)->dccpd_seq,
DCCP_ACKVEC_STATE_RECEIVED))
goto discard;

ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);

return __dccp_rcv_established(sk, skb, dh, len);
discard:
__kfree_skb(skb);
return 0;
}

EXPORT_SYMBOL_GPL(dccp_rcv_established);

static int dccp_rcv_request_sent_state_process(struct sock *sk,
Expand Down Expand Up @@ -400,9 +412,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,

if (dh->dccph_type == DCCP_PKT_DATAACK ||
dh->dccph_type == DCCP_PKT_DATA) {
dccp_rcv_established(sk, skb, dh, len);
__dccp_rcv_established(sk, skb, dh, len);
queued = 1; /* packet was queued
(by dccp_rcv_established) */
(by __dccp_rcv_established) */
}
break;
}
Expand Down

0 comments on commit 709dd3a

Please sign in to comment.