]> err.no Git - linux-2.6/blobdiff - net/dccp/input.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild
[linux-2.6] / net / dccp / input.c
index 68b6e72551efe87b17fdbc39b461c900da254795..ef29cef1dafe238196224bd8aed79cc139a2c329 100644 (file)
@@ -31,14 +31,10 @@ static void dccp_fin(struct sock *sk, struct sk_buff *skb)
 
 static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
 {
-       switch (sk->sk_state) {
-       case DCCP_PARTOPEN:
-       case DCCP_OPEN:
-               dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED);
-               dccp_fin(sk, skb);
-               dccp_set_state(sk, DCCP_CLOSED);
-               break;
-       }
+       dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED);
+       dccp_fin(sk, skb);
+       dccp_set_state(sk, DCCP_CLOSED);
+       sk_wake_async(sk, 1, POLL_HUP);
 }
 
 static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
@@ -54,13 +50,8 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
                return;
        }
 
-       switch (sk->sk_state) {
-       case DCCP_PARTOPEN:
-       case DCCP_OPEN:
-               dccp_set_state(sk, DCCP_CLOSING);
-               dccp_send_close(sk);
-               break;
-       }
+       dccp_set_state(sk, DCCP_CLOSING);
+       dccp_send_close(sk, 0);
 }
 
 static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
@@ -118,8 +109,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
        lawl = dp->dccps_awl;
 
        if (dh->dccph_type == DCCP_PKT_CLOSEREQ ||
-                  dh->dccph_type == DCCP_PKT_CLOSE ||
-                  dh->dccph_type == DCCP_PKT_RESET) {
+           dh->dccph_type == DCCP_PKT_CLOSE ||
+           dh->dccph_type == DCCP_PKT_RESET) {
                lswl = dp->dccps_gsr;
                dccp_inc_seqno(&lswl);
                lawl = dp->dccps_gar;
@@ -136,7 +127,21 @@ 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 {
-               LIMIT_NETDEBUG("Step 6 failed, sending SYNC...\n");
+               LIMIT_NETDEBUG(KERN_WARNING "DCCP: Step 6 failed for %s packet, "
+                                           "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "
+                                           "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), "
+                                           "sending SYNC...\n",
+                              dccp_packet_name(dh->dccph_type),
+                              (unsigned long long) lswl,
+                              (unsigned long long)
+                              DCCP_SKB_CB(skb)->dccpd_seq,
+                              (unsigned long long) dp->dccps_swh,
+                              (DCCP_SKB_CB(skb)->dccpd_ack_seq ==
+                               DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists",
+                              (unsigned long long) lawl,
+                              (unsigned long long)
+                              DCCP_SKB_CB(skb)->dccpd_ack_seq,
+                              (unsigned long long) dp->dccps_awh);
                dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC);
                return -1;
        }
@@ -168,8 +173,8 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
                                     DCCP_SKB_CB(skb)->dccpd_seq,
                                     DCCP_ACKPKTS_STATE_RECEIVED)) {
-                       LIMIT_NETDEBUG(KERN_INFO "DCCP: acknowledgeable "
-                                                "packets buffer full!\n");
+                       LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
+                                                   "packets buffer full!\n");
                        ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
                        inet_csk_schedule_ack(sk);
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
@@ -306,7 +311,19 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                }
 
                dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
-               dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq);
+               dccp_update_gsr(sk, dp->dccps_isr);
+               /*
+                * SWL and AWL are initially adjusted so that they are not less than
+                * the initial Sequence Numbers received and sent, respectively:
+                *      SWL := max(GSR + 1 - floor(W/4), ISR),
+                *      AWL := max(GSS - W' + 1, ISS).
+                * These adjustments MUST be applied only at the beginning of the
+                * connection.
+                *
+                * AWL was adjusted in dccp_v4_connect -acme
+                */
+               dccp_set_seqno(&dp->dccps_swl,
+                              max48(dp->dccps_swl, dp->dccps_isr));
 
                if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 ||
                    ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) {
@@ -536,6 +553,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
                               DCCP_PKT_SYNC);
                goto discard;
+       } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
+               dccp_rcv_closereq(sk, skb);
+               goto discard;
+       } else if (dh->dccph_type == DCCP_PKT_CLOSE) {
+               dccp_rcv_close(sk, skb);
+               return 0;
        }
 
        switch (sk->sk_state) {