]> err.no Git - linux-2.6/blobdiff - net/dccp/input.c
[PATCH] ipc: convert /proc/sysvipc/* to generic seq_file interface
[linux-2.6] / net / dccp / input.c
index 9dadfc362511ef31cdd087871f8f88ad9d5db1f8..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)
@@ -50,17 +46,12 @@ 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;
        }
 
-       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)
@@ -76,8 +67,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 +89,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,9 +105,12 @@ 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 ||
-                  dh->dccph_type == DCCP_PKT_CLOSE ||
-                  dh->dccph_type == DCCP_PKT_RESET) {
+       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;
                dccp_inc_seqno(&lswl);
                lawl = dp->dccps_gar;
@@ -132,8 +127,22 @@ 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(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;
        }
 
@@ -164,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,
@@ -242,9 +251,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);
@@ -290,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) {
@@ -517,8 +550,15 @@ 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;
+       } 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) {