[DCCP] CCID2: Drop sock reference count on timer expiration and reset.
[powerpc.git] / net / dccp / ipv4.c
index 00f9832..fcfb486 100644 (file)
@@ -28,6 +28,7 @@
 #include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
+#include "feat.h"
 
 struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
        .lhash_lock     = RW_LOCK_UNLOCKED,
@@ -119,7 +120,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (err != 0)
                goto failure;
 
-       err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+       err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport,
+                               sk);
        if (err != 0)
                goto failure;
 
@@ -534,7 +536,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        if (req == NULL)
                goto drop;
 
-       /* FIXME: process options */
+       if (dccp_parse_options(sk, skb))
+               goto drop;
 
        dccp_openreq_init(req, &dp, skb);
 
@@ -1040,13 +1043,6 @@ int dccp_v4_init_sock(struct sock *sk)
        dccp_options_init(&dp->dccps_options);
        do_gettimeofday(&dp->dccps_epoch);
 
-       if (dp->dccps_options.dccpo_send_ack_vector) {
-               dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
-                                                          GFP_KERNEL);
-               if (dp->dccps_hc_rx_ackvec == NULL)
-                       return -ENOMEM;
-       }
-
        /*
         * FIXME: We're hardcoding the CCID, and doing this at this point makes
         * the listening (master) sock get CCID control blocks, which is not
@@ -1055,6 +1051,13 @@ int dccp_v4_init_sock(struct sock *sk)
         * setsockopt(CCIDs-I-want/accept). -acme
         */
        if (likely(!dccp_ctl_socket_init)) {
+               int rc;
+
+               if (dp->dccps_options.dccpo_send_ack_vector) {
+                       dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);
+                       if (dp->dccps_hc_rx_ackvec == NULL)
+                               return -ENOMEM;
+               }
                dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
                                                 sk);
                dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
@@ -1070,8 +1073,16 @@ int dccp_v4_init_sock(struct sock *sk)
                        dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
                        return -ENOMEM;
                }
-       } else
+
+               rc = dccp_feat_init(sk);
+               if (rc)
+                       return rc;
+       } else {
+               /* control socket doesn't need feat nego */
+               INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending);
+               INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf);
                dccp_ctl_socket_init = 0;
+       }
 
        dccp_init_xmit_timers(sk);
        icsk->icsk_rto = DCCP_TIMEOUT_INIT;
@@ -1082,6 +1093,7 @@ int dccp_v4_init_sock(struct sock *sk)
        dp->dccps_mss_cache = 536;
        dp->dccps_role = DCCP_ROLE_UNDEFINED;
        dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
+       dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1;
 
        return 0;
 }
@@ -1118,6 +1130,9 @@ int dccp_v4_destroy_sock(struct sock *sk)
        ccid_exit(dp->dccps_hc_tx_ccid, sk);
        dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
 
+       /* clean up feature negotiation state */
+       dccp_feat_clean(sk);
+
        return 0;
 }