diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-08-17 03:10:59 -0300 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 16:01:50 -0700 |
commit | e92ae93a8aa66aea12935420cb22d4df1c18d023 (patch) | |
tree | 61ffc292a8e437f7d44bbfe00c4e052f7488dd25 /net/dccp | |
parent | ba602a816132dcc66e875dddf2c62512a9f6f8cb (diff) | |
download | lwn-e92ae93a8aa66aea12935420cb22d4df1c18d023.tar.gz lwn-e92ae93a8aa66aea12935420cb22d4df1c18d023.zip |
[DCCP]: Send SYNCACK packets in response to SYNC packets
Also fix step 6 when receiving SYNC or SYNCACK packets, i.e. we were not using
the updated swl.
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/dccp.h | 3 | ||||
-rw-r--r-- | net/dccp/input.c | 33 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 18 | ||||
-rw-r--r-- | net/dccp/output.c | 5 |
4 files changed, 40 insertions, 19 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index fff794c8dfff..4efdce47000b 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -122,7 +122,8 @@ extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); extern int dccp_send_response(struct sock *sk); extern void dccp_send_ack(struct sock *sk); extern void dccp_send_delayed_ack(struct sock *sk); -extern void dccp_send_sync(struct sock *sk, u64 seq); +extern void dccp_send_sync(struct sock *sk, const u64 seq, + const enum dccp_pkt_type pkt_type); extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, const int len); diff --git a/net/dccp/input.c b/net/dccp/input.c index 9dadfc362511..68b6e72551ef 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -50,7 +50,7 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) * Drop packet and return */ if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) { - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq); + dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); return; } @@ -76,8 +76,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) { const struct dccp_hdr *dh = dccp_hdr(skb); struct dccp_sock *dp = dccp_sk(sk); - u64 lswl = dp->dccps_swl; - u64 lawl = dp->dccps_awl; + u64 lswl, lawl; /* * Step 5: Prepare sequence numbers for Sync @@ -99,6 +98,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq); else return -1; + } + /* * Step 6: Check sequence numbers * Let LSWL = S.SWL and LAWL = S.AWL @@ -113,7 +114,10 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) * Send Sync packet acknowledging P.seqno * Drop packet and return */ - } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ || + lswl = dp->dccps_swl; + lawl = dp->dccps_awl; + + if (dh->dccph_type == DCCP_PKT_CLOSEREQ || dh->dccph_type == DCCP_PKT_CLOSE || dh->dccph_type == DCCP_PKT_RESET) { lswl = dp->dccps_gsr; @@ -132,8 +136,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) DCCP_PKT_WITHOUT_ACK_SEQ)) dp->dccps_gar = DCCP_SKB_CB(skb)->dccpd_ack_seq; } else { - dccp_pr_debug("Step 6 failed, sending SYNC...\n"); - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq); + LIMIT_NETDEBUG("Step 6 failed, sending SYNC...\n"); + dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); return -1; } @@ -242,9 +246,21 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, check_seq: if (!before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_osr)) { send_sync: - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq); + dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_PKT_SYNC); } break; + case DCCP_PKT_SYNC: + dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_PKT_SYNCACK); + /* + * From the draft: + * + * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets + * MAY have non-zero-length application data areas, whose + * contents * receivers MUST ignore. + */ + goto discard; } DCCP_INC_STATS_BH(DCCP_MIB_INERRS); @@ -517,7 +533,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, dh->dccph_type == DCCP_PKT_REQUEST) || (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) { - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq); + dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_PKT_SYNC); goto discard; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index bc3cfc0533cc..335e00e9631d 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -376,7 +376,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, * probing, since DCCP-Sync probes do not risk application * data loss. */ - dccp_send_sync(sk, dp->dccps_gsr); + dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC); } /* else let the usual retransmit timer handle it */ } @@ -1008,7 +1008,7 @@ static inline int dccp_invalid_packet(struct sk_buff *skb) return 1; if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) { - dccp_pr_debug("pskb_may_pull failed\n"); + printk(KERN_WARNING "DCCP: pskb_may_pull failed\n"); return 1; } @@ -1016,7 +1016,7 @@ static inline int dccp_invalid_packet(struct sk_buff *skb) /* If the packet type is not understood, drop packet and return */ if (dh->dccph_type >= DCCP_PKT_INVALID) { - dccp_pr_debug("invalid packet type\n"); + printk(KERN_WARNING "DCCP: invalid packet type\n"); return 1; } @@ -1025,12 +1025,13 @@ static inline int dccp_invalid_packet(struct sk_buff *skb) * packet, drop packet and return */ if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { - dccp_pr_debug("Offset(%u) too small 1\n", dh->dccph_doff); + printk(KERN_WARNING "DCCP: Offset(%u) too small 1\n", + dh->dccph_doff); return 1; } if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) { - dccp_pr_debug("P.Data Offset(%u) too small 2\n", + printk(KERN_WARNING "DCCP: P.Data Offset(%u) too small 2\n", dh->dccph_doff); return 1; } @@ -1045,15 +1046,16 @@ static inline int dccp_invalid_packet(struct sk_buff *skb) dh->dccph_type != DCCP_PKT_DATA && dh->dccph_type != DCCP_PKT_ACK && dh->dccph_type != DCCP_PKT_DATAACK) { - dccp_pr_debug("P.type (%s) not Data, Ack nor DataAck and " - "P.X == 0\n", dccp_packet_name(dh->dccph_type)); + printk(KERN_WARNING "DCCP: P.type (%s) not Data, Ack nor " + "DataAck and P.X == 0\n", + dccp_packet_name(dh->dccph_type)); return 1; } /* If the header checksum is incorrect, drop packet and return */ if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr, skb->nh.iph->daddr) < 0) { - dccp_pr_debug("header checksum is incorrect\n"); + printk(KERN_WARNING "DCCP: header checksum is incorrect\n"); return 1; } diff --git a/net/dccp/output.c b/net/dccp/output.c index dcc061bed924..384fd0920983 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -404,7 +404,8 @@ void dccp_send_delayed_ack(struct sock *sk) sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout); } -void dccp_send_sync(struct sock *sk, u64 seq) +void dccp_send_sync(struct sock *sk, const u64 seq, + const enum dccp_pkt_type pkt_type) { /* * We are not putting this on the write queue, so @@ -420,7 +421,7 @@ void dccp_send_sync(struct sock *sk, u64 seq) /* Reserve space for headers and prepare control bits. */ skb_reserve(skb, MAX_DCCP_HEADER); skb->csum = 0; - DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_SYNC; + DCCP_SKB_CB(skb)->dccpd_type = pkt_type; DCCP_SKB_CB(skb)->dccpd_seq = seq; skb_set_owner_w(skb, sk); |