]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/dccp/input.c
[ALSA] at73c213: monaural support
[linux-2.6-omap-h63xx.git] / net / dccp / input.c
index fe4b0fbfa5080ebf049f36b01f12c5c0e9185cdc..08392ed86c25403ea574c1e2b39786b8488e4625 100644 (file)
 /* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
 int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
 
-static void dccp_fin(struct sock *sk, struct sk_buff *skb)
+static void dccp_enqueue_skb(struct sock *sk, struct sk_buff *skb)
 {
-       sk->sk_shutdown |= RCV_SHUTDOWN;
-       sock_set_flag(sk, SOCK_DONE);
        __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4);
        __skb_queue_tail(&sk->sk_receive_queue, skb);
        skb_set_owner_r(skb, sk);
        sk->sk_data_ready(sk, 0);
 }
 
+static void dccp_fin(struct sock *sk, struct sk_buff *skb)
+{
+       /*
+        * On receiving Close/CloseReq, both RD/WR shutdown are performed.
+        * RFC 4340, 8.3 says that we MAY send further Data/DataAcks after
+        * receiving the closing segment, but there is no guarantee that such
+        * data will be processed at all.
+        */
+       sk->sk_shutdown = SHUTDOWN_MASK;
+       sock_set_flag(sk, SOCK_DONE);
+       dccp_enqueue_skb(sk, skb);
+}
+
 static int dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
 {
        int queued = 0;
@@ -282,10 +293,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                 * - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening"
                 * - sk_receive_queue is full, use Code 2, "Receive Buffer"
                 */
-               __skb_pull(skb, dh->dccph_doff * 4);
-               __skb_queue_tail(&sk->sk_receive_queue, skb);
-               skb_set_owner_r(skb, sk);
-               sk->sk_data_ready(sk, 0);
+               dccp_enqueue_skb(sk, skb);
                return 0;
        case DCCP_PKT_ACK:
                goto discard;
@@ -361,7 +369,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
        if (dccp_check_seqno(sk, skb))
                goto discard;
 
-       if (dccp_parse_options(sk, skb))
+       if (dccp_parse_options(sk, NULL, skb))
                goto discard;
 
        if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
@@ -419,7 +427,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                        goto out_invalid_packet;
                }
 
-               if (dccp_parse_options(sk, skb))
+               if (dccp_parse_options(sk, NULL, skb))
                        goto out_invalid_packet;
 
                /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
@@ -601,7 +609,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                /*
                 * Step 8: Process options and mark acknowledgeable
                 */
-               if (dccp_parse_options(sk, skb))
+               if (dccp_parse_options(sk, NULL, skb))
                        goto discard;
 
                if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
@@ -629,16 +637,14 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                return 0;
                /*
                 *   Step 7: Check for unexpected packet types
-                *      If (S.is_server and P.type == CloseReq)
-                *          or (S.is_server and P.type == Response)
+                *      If (S.is_server and P.type == Response)
                 *          or (S.is_client and P.type == Request)
                 *          or (S.state == RESPOND and P.type == Data),
                 *        Send Sync packet acknowledging P.seqno
                 *        Drop packet and return
                 */
        } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
-                   (dh->dccph_type == DCCP_PKT_RESPONSE ||
-                    dh->dccph_type == DCCP_PKT_CLOSEREQ)) ||
+                   dh->dccph_type == DCCP_PKT_RESPONSE) ||
                    (dp->dccps_role == DCCP_ROLE_CLIENT &&
                     dh->dccph_type == DCCP_PKT_REQUEST) ||
                    (sk->sk_state == DCCP_RESPOND &&