fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / dccp / input.c
index b6cba72..565bc80 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/input.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -10,7 +10,6 @@
  *     2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/dccp.h>
 #include <linux/skbuff.h>
 
@@ -32,7 +31,7 @@ static void dccp_fin(struct sock *sk, struct sk_buff *skb)
 
 static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
 {
-       dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED);
+       dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED);
        dccp_fin(sk, skb);
        dccp_set_state(sk, DCCP_CLOSED);
        sk_wake_async(sk, 1, POLL_HUP);
@@ -56,11 +55,11 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
        dccp_send_close(sk, 0);
 }
 
-static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
+static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
 
-       if (dp->dccps_options.dccpo_send_ack_vector)
+       if (dccp_msk(sk)->dccpms_send_ack_vector)
                dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,
                                            DCCP_SKB_CB(skb)->dccpd_ack_seq);
 }
@@ -83,7 +82,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
         *        Otherwise,
         *           Drop packet and return
         */
-       if (dh->dccph_type == DCCP_PKT_SYNC || 
+       if (dh->dccph_type == DCCP_PKT_SYNC ||
            dh->dccph_type == DCCP_PKT_SYNCACK) {
                if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
                              dp->dccps_awl, dp->dccps_awh) &&
@@ -129,21 +128,18 @@ 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(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_WARN("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);
+                         (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;
        }
@@ -151,9 +147,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
        return 0;
 }
 
-static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
-                                        const struct dccp_hdr *dh,
-                                        const unsigned len)
+static 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);
 
@@ -190,8 +185,8 @@ static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                dccp_rcv_close(sk, skb);
                return 0;
        case DCCP_PKT_REQUEST:
-               /* Step 7 
-                *   or (S.is_server and P.type == Response)
+               /* Step 7
+                *   or (S.is_server and P.type == Response)
                 *   or (S.is_client and P.type == Request)
                 *   or (S.state >= OPEN and P.type == Request
                 *      and P.seqno >= S.OSR)
@@ -218,11 +213,11 @@ send_sync:
                dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
                               DCCP_PKT_SYNCACK);
                /*
-                * From the draft:
+                * From RFC 4340, sec. 5.7
                 *
                 * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets
                 * MAY have non-zero-length application data areas, whose
-                * contents receivers MUST ignore.
+                * contents receivers MUST ignore.
                 */
                goto discard;
        }
@@ -247,14 +242,24 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
        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 &&
+       if (dccp_msk(sk)->dccpms_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);
+       /*
+        * Deliver to the CCID module in charge.
+        * FIXME: Currently DCCP operates one-directional only, i.e. a listening
+        *        server is not at the same time a connecting client. There is
+        *        not much sense in delivering to both rx/tx sides at the moment
+        *        (only one is active at a time); when moving to bidirectional
+        *        service, this needs to be revised.
+        */
+       if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+               ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+       else
+               ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
 
        return __dccp_rcv_established(sk, skb, dh, len);
 discard:
@@ -269,7 +274,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                                               const struct dccp_hdr *dh,
                                               const unsigned len)
 {
-       /* 
+       /*
         *  Step 4: Prepare sequence numbers in REQUEST
         *     If S.state == REQUEST,
         *        If (P.type == Response or P.type == Reset)
@@ -300,7 +305,10 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                        goto out_invalid_packet;
                }
 
-                if (dp->dccps_options.dccpo_send_ack_vector &&
+               if (dccp_parse_options(sk, skb))
+                       goto out_invalid_packet;
+
+                if (dccp_msk(sk)->dccpms_send_ack_vector &&
                     dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
                                     DCCP_SKB_CB(skb)->dccpd_seq,
                                     DCCP_ACKVEC_STATE_RECEIVED))
@@ -321,14 +329,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                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) {
-                       ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
-                       ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
-                       /* FIXME: send appropriate RESET code */
-                       goto out_invalid_packet;
-               }
-
                dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
 
                /*
@@ -342,7 +342,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                 *            from the Response * /
                 *        S.state := PARTOPEN
                 *        Set PARTOPEN timer
-                *        Continue with S.state == PARTOPEN
+                *        Continue with S.state == PARTOPEN
                 *        / * Step 12 will send the Ack completing the
                 *            three-way handshake * /
                 */
@@ -373,7 +373,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                         */
                        __kfree_skb(skb);
                        return 0;
-               } 
+               }
                dccp_send_ack(sk);
                return -1;
        }
@@ -381,7 +381,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
 out_invalid_packet:
        /* dccp_v4_do_rcv will send a reset */
        DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
-       return 1; 
+       return 1;
 }
 
 static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
@@ -438,29 +438,25 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 
        /*
         *  Step 3: Process LISTEN state
-        *      (Continuing from dccp_v4_do_rcv and dccp_v6_do_rcv)
         *
         *     If S.state == LISTEN,
-        *        If P.type == Request or P contains a valid Init Cookie
-        *              option,
-        *           * Must scan the packet's options to check for an Init
-        *              Cookie.  Only the Init Cookie is processed here,
-        *              however; other options are processed in Step 8.  This
-        *              scan need only be performed if the endpoint uses Init
-        *              Cookies *
-        *           * Generate a new socket and switch to that socket *
-        *           Set S := new socket for this port pair
-        *           S.state = RESPOND
-        *           Choose S.ISS (initial seqno) or set from Init Cookie
-        *           Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
-        *           Continue with S.state == RESPOND
-        *           * A Response packet will be generated in Step 11 *
-        *        Otherwise,
-        *           Generate Reset(No Connection) unless P.type == Reset
-        *           Drop packet and return
-        *
-        * NOTE: the check for the packet types is done in
-        *       dccp_rcv_state_process
+        *       If P.type == Request or P contains a valid Init Cookie option,
+        *            (* Must scan the packet's options to check for Init
+        *               Cookies.  Only Init Cookies are processed here,
+        *               however; other options are processed in Step 8.  This
+        *               scan need only be performed if the endpoint uses Init
+        *               Cookies *)
+        *            (* Generate a new socket and switch to that socket *)
+        *            Set S := new socket for this port pair
+        *            S.state = RESPOND
+        *            Choose S.ISS (initial seqno) or set from Init Cookies
+        *            Initialize S.GAR := S.ISS
+        *            Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init
+        *            Cookies Continue with S.state == RESPOND
+        *            (* A Response packet will be generated in Step 11 *)
+        *       Otherwise,
+        *            Generate Reset(No Connection) unless P.type == Reset
+        *            Drop packet and return
         */
        if (sk->sk_state == DCCP_LISTEN) {
                if (dh->dccph_type == DCCP_PKT_REQUEST) {
@@ -492,14 +488,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
                        dccp_event_ack_recv(sk, skb);
 
-               if (dp->dccps_options.dccpo_send_ack_vector &&
+               if (dccp_msk(sk)->dccpms_send_ack_vector &&
                    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
-                                   DCCP_SKB_CB(skb)->dccpd_seq,
-                                   DCCP_ACKVEC_STATE_RECEIVED))
-                       goto discard;
+                                   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);
+               /* XXX see the comments in dccp_rcv_established about this */
+               if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+                       ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+               else
+                       ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
        }
 
        /*
@@ -581,7 +580,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                }
        }
 
-       if (!queued) { 
+       if (!queued) {
 discard:
                __kfree_skb(skb);
        }