]> err.no Git - linux-2.6/blobdiff - net/dccp/ipv4.c
[DCCP]: Generalize dccp_v4_send_reset
[linux-2.6] / net / dccp / ipv4.c
index c363051a7f1652496a85b4e5611f76f586a43251..3baf4c76a89d0311b12ede5242989a878b4b1dec 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <net/icmp.h>
 #include <net/inet_hashtables.h>
+#include <net/inet_sock.h>
 #include <net/sock.h>
 #include <net/timewait_sock.h>
 #include <net/tcp_states.h>
@@ -27,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,
@@ -118,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;
 
@@ -454,32 +457,6 @@ void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
 
 EXPORT_SYMBOL_GPL(dccp_v4_send_check);
 
-int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
-{
-       struct sk_buff *skb;
-       /*
-        * FIXME: what if rebuild_header fails?
-        * Should we be doing a rebuild_header here?
-        */
-       int err = inet_sk_rebuild_header(sk);
-
-       if (err != 0)
-               return err;
-
-       skb = dccp_make_reset(sk, sk->sk_dst_cache, code);
-       if (skb != NULL) {
-               const struct inet_sock *inet = inet_sk(sk);
-
-               memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-               err = ip_build_and_send_pkt(skb, sk,
-                                           inet->saddr, inet->daddr, NULL);
-               if (err == NET_XMIT_CN)
-                       err = 0;
-       }
-
-       return err;
-}
-
 static inline u64 dccp_v4_init_sequence(const struct sock *sk,
                                        const struct sk_buff *skb)
 {
@@ -495,9 +472,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        struct dccp_sock dp;
        struct request_sock *req;
        struct dccp_request_sock *dreq;
-       const __u32 saddr = skb->nh.iph->saddr;
-       const __u32 daddr = skb->nh.iph->daddr;
-       const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
+       const __be32 saddr = skb->nh.iph->saddr;
+       const __be32 daddr = skb->nh.iph->daddr;
+       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
        struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
        __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 
@@ -533,7 +510,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);
 
@@ -658,8 +636,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
        return sk;
 }
 
-int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr,
-                    const u32 daddr)
+int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr,
+                    const __be32 daddr)
 {
        const struct dccp_hdr* dh = dccp_hdr(skb);
        int checksum_len;
@@ -679,7 +657,7 @@ int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr,
 }
 
 static int dccp_v4_verify_checksum(struct sk_buff *skb,
-                                  const u32 saddr, const u32 daddr)
+                                  const __be32 saddr, const __be32 daddr)
 {
        struct dccp_hdr *dh = dccp_hdr(skb);
        int checksum_len;
@@ -914,7 +892,6 @@ int dccp_v4_rcv(struct sk_buff *skb)
 {
        const struct dccp_hdr *dh;
        struct sock *sk;
-       int rc;
 
        /* Step 1: Check header basics: */
 
@@ -984,28 +961,11 @@ int dccp_v4_rcv(struct sk_buff *skb)
                 goto do_time_wait;
        }
 
-       if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
-               dccp_pr_debug("xfrm4_policy_check failed\n");
+       if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_and_relse;
-       }
-
-        if (sk_filter(sk, skb, 0)) {
-               dccp_pr_debug("sk_filter failed\n");
-                goto discard_and_relse;
-       }
+       nf_reset(skb);
 
-       skb->dev = NULL;
-
-       bh_lock_sock(sk);
-       rc = 0;
-       if (!sock_owned_by_user(sk))
-               rc = dccp_v4_do_rcv(sk, skb);
-       else
-               sk_add_backlog(sk, skb);
-       bh_unlock_sock(sk);
-
-       sock_put(sk);
-       return rc;
+       return sk_receive_skb(sk, skb);
 
 no_dccp_socket:
        if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
@@ -1057,13 +1017,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
@@ -1072,14 +1025,26 @@ int dccp_v4_init_sock(struct sock *sk)
         * setsockopt(CCIDs-I-want/accept). -acme
         */
        if (likely(!dccp_ctl_socket_init)) {
-               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,
-                                                sk);
-               if (dp->dccps_hc_rx_ccid == NULL ||
-                   dp->dccps_hc_tx_ccid == NULL) {
-                       ccid_exit(dp->dccps_hc_rx_ccid, sk);
-                       ccid_exit(dp->dccps_hc_tx_ccid, sk);
+               int rc = dccp_feat_init(sk);
+
+               if (rc)
+                       return 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_hc_rx_new(dp->dccps_options.dccpo_rx_ccid,
+                                              sk, GFP_KERNEL);
+               dp->dccps_hc_tx_ccid =
+                               ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid,
+                                              sk, GFP_KERNEL);
+               if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
+                            dp->dccps_hc_tx_ccid == NULL)) {
+                       ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+                       ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
                        if (dp->dccps_options.dccpo_send_ack_vector) {
                                dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
                                dp->dccps_hc_rx_ackvec = NULL;
@@ -1087,8 +1052,12 @@ int dccp_v4_init_sock(struct sock *sk)
                        dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
                        return -ENOMEM;
                }
-       } else
+       } 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;
@@ -1099,6 +1068,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;
 }
@@ -1125,16 +1095,17 @@ int dccp_v4_destroy_sock(struct sock *sk)
        kfree(dp->dccps_service_list);
        dp->dccps_service_list = NULL;
 
-       ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
-       ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
        if (dp->dccps_options.dccpo_send_ack_vector) {
                dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
                dp->dccps_hc_rx_ackvec = NULL;
        }
-       ccid_exit(dp->dccps_hc_rx_ccid, sk);
-       ccid_exit(dp->dccps_hc_tx_ccid, sk);
+       ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+       ccid_hc_tx_delete(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;
 }