]> err.no Git - linux-2.6/commitdiff
[DCCP] ipv6: Add missing ipv6 control socket
authorArnaldo Carvalho de Melo <acme@mandriva.com>
Tue, 21 Mar 2006 06:00:37 +0000 (22:00 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Mar 2006 06:00:37 +0000 (22:00 -0800)
I guess I forgot to add it, nah, now it just works:

18:04:33.274066 IP6 ::1.1476 > ::1.5001: request (service=0)
18:04:33.334482 IP6 ::1.5001 > ::1.1476: reset (code=bad_service_code)

Ditched IP_DCCP_UNLOAD_HACK, as now we would have to do it for both
IPv6 and IPv4, so I'll come up with another way for freeing the
control sockets in upcoming changesets.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/dccp/Kconfig
net/dccp/ccids/ccid3.c
net/dccp/dccp.h
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/proto.c

index 24a6981e209a542ba425704965aa6b538bbfda7c..7e096ba8454fcef7e6e0888f08fdd4c415198674 100644 (file)
@@ -40,15 +40,6 @@ config IP_DCCP_DEBUG
 
          Just say N.
 
-config IP_DCCP_UNLOAD_HACK
-       depends on IP_DCCP=m && IP_DCCP_CCID3=m
-       bool "DCCP control sock unload hack"
-       ---help---
-         Enable this to be able to unload the dccp module when the it
-         has only one refcount held, the control sock one. Just execute
-         "rmmod dccp_ccid3 dccp"
-
-         Just say N.
 endmenu
 
 endmenu
index ff6a0d7076ef5f65e8518ed10338fda0ab09069e..ff426a9009993445a15cfcac6c88be1e39e07913 100644 (file)
@@ -1211,15 +1211,6 @@ module_init(ccid3_module_init);
 
 static __exit void ccid3_module_exit(void)
 {
-#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
-       /*
-        * Hack to use while developing, so that we get rid of the control
-        * sock, that is what keeps a refcount on dccp.ko -acme
-        */
-       extern void dccp_ctl_sock_exit(void);
-
-       dccp_ctl_sock_exit();
-#endif
        ccid_unregister(&ccid3);
 
        if (ccid3_tx_hist != NULL) {
index 6fcc9d47ae8c1e9d42feea4356d1250a6a47535d..d57d213511490e659b3feebbbb50d33d60f1d0c2 100644 (file)
@@ -177,7 +177,7 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                                const struct dccp_hdr *dh, const unsigned len);
 
-extern int dccp_init_sock(struct sock *sk);
+extern int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized);
 extern int dccp_destroy_sock(struct sock *sk);
 
 extern void            dccp_close(struct sock *sk, long timeout);
@@ -337,8 +337,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
                               unsigned char option,
                               const void *value, unsigned char len);
 
-extern struct socket *dccp_ctl_socket;
-
 extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
 
 static inline suseconds_t timeval_usecs(const struct timeval *tv)
index 3fe958eb4bf372c69c029529d219670fde8544a8..f53bce590ade68f1154f90c7515882ad4ab1a27a 100644 (file)
 #include "dccp.h"
 #include "feat.h"
 
+/*
+ * This is the global socket data structure used for responding to
+ * the Out-of-the-blue (OOTB) packets. A control sock will be created
+ * for this socket at the initialization time.
+ */
+static struct socket *dccp_v4_ctl_socket;
+
 static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
 {
        return inet_csk_get_port(&dccp_hashinfo, sk, snum,
@@ -226,11 +233,11 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
        dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
                         DCCP_SKB_CB(rxskb)->dccpd_seq);
 
-       bh_lock_sock(dccp_ctl_socket->sk);
-       err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
+       bh_lock_sock(dccp_v4_ctl_socket->sk);
+       err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
                                    rxskb->nh.iph->daddr,
                                    rxskb->nh.iph->saddr, NULL);
-       bh_unlock_sock(dccp_ctl_socket->sk);
+       bh_unlock_sock(dccp_v4_ctl_socket->sk);
 
        if (err == NET_XMIT_CN || err == 0) {
                DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -704,7 +711,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
        if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
                return;
 
-       dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb);
+       dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
        if (dst == NULL)
                return;
 
@@ -741,11 +748,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
        dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
                                              rxskb->nh.iph->daddr);
 
-       bh_lock_sock(dccp_ctl_socket->sk);
-       err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
+       bh_lock_sock(dccp_v4_ctl_socket->sk);
+       err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
                                    rxskb->nh.iph->daddr,
                                    rxskb->nh.iph->saddr, NULL);
-       bh_unlock_sock(dccp_ctl_socket->sk);
+       bh_unlock_sock(dccp_v4_ctl_socket->sk);
 
        if (err == NET_XMIT_CN || err == 0) {
                DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -997,10 +1004,15 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
 
 static int dccp_v4_init_sock(struct sock *sk)
 {
-       const int err = dccp_init_sock(sk);
+       static __u8 dccp_v4_ctl_sock_initialized;
+       int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
 
-       if (err == 0)
+       if (err == 0) {
+               if (unlikely(!dccp_v4_ctl_sock_initialized))
+                       dccp_v4_ctl_sock_initialized = 1;
                inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
+       }
+
        return err;
 }
 
@@ -1087,48 +1099,29 @@ static struct inet_protosw dccp_v4_protosw = {
        .flags          = INET_PROTOSW_ICSK,
 };
 
-/*
- * This is the global socket data structure used for responding to
- * the Out-of-the-blue (OOTB) packets. A control sock will be created
- * for this socket at the initialization time.
- */
-struct socket *dccp_ctl_socket;
-
-static char dccp_ctl_socket_err_msg[] __initdata =
+static char dccp_v4_ctl_socket_err_msg[] __initdata =
        KERN_ERR "DCCP: Failed to create the control socket.\n";
 
-static int __init dccp_ctl_sock_init(void)
+static int __init dccp_v4_ctl_sock_init(void)
 {
        int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
-                                 &dccp_ctl_socket);
+                                 &dccp_v4_ctl_socket);
        if (rc < 0)
-               printk(dccp_ctl_socket_err_msg);
+               printk(dccp_v4_ctl_socket_err_msg);
        else {
-               dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
-               inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1;
+               dccp_v4_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
+               inet_sk(dccp_v4_ctl_socket->sk)->uc_ttl = -1;
 
                /* Unhash it so that IP input processing does not even
                 * see it, we do not wish this socket to see incoming
                 * packets.
                 */
-               dccp_ctl_socket->sk->sk_prot->unhash(dccp_ctl_socket->sk);
+               dccp_v4_ctl_socket->sk->sk_prot->unhash(dccp_v4_ctl_socket->sk);
        }
 
        return rc;
 }
 
-#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
-void dccp_ctl_sock_exit(void)
-{
-       if (dccp_ctl_socket != NULL) {
-               sock_release(dccp_ctl_socket);
-               dccp_ctl_socket = NULL;
-       }
-}
-
-EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit);
-#endif
-
 static int __init dccp_v4_init(void)
 {
        int err = proto_register(&dccp_v4_prot, 1);
@@ -1142,7 +1135,7 @@ static int __init dccp_v4_init(void)
 
        inet_register_protosw(&dccp_v4_protosw);
 
-       err = dccp_ctl_sock_init();
+       err = dccp_v4_ctl_sock_init();
        if (err)
                goto out_unregister_protosw;
 out:
index 904967bf2fe943af6cce03ed921468baaac6153e..3c9f0836404fb59f4730a7949e8be7b0961dec21 100644 (file)
@@ -33,6 +33,9 @@
 #include "dccp.h"
 #include "ipv6.h"
 
+/* Socket used for sending RSTs and ACKs */
+static struct socket *dccp_v6_ctl_socket;
+
 static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
 static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
                                   struct request_sock *req);
@@ -568,7 +571,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
        /* sk = NULL, but it is safe for now. RST socket required. */
        if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
                if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
-                       ip6_xmit(NULL, skb, &fl, NULL, 0);
+                       ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
                        DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
                        DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
                        return;
@@ -623,7 +626,7 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
 
        if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
                if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
-                       ip6_xmit(NULL, skb, &fl, NULL, 0);
+                       ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
                        DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
                        return;
                }
@@ -1146,10 +1149,14 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
  */
 static int dccp_v6_init_sock(struct sock *sk)
 {
-       int err = dccp_init_sock(sk);
+       static __u8 dccp_v6_ctl_sock_initialized;
+       int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
 
-       if (err == 0)
+       if (err == 0) {
+               if (unlikely(!dccp_v6_ctl_sock_initialized))
+                       dccp_v6_ctl_sock_initialized = 1;
                inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
+       }
 
        return err;
 }
@@ -1222,6 +1229,29 @@ static struct inet_protosw dccp_v6_protosw = {
        .flags          = INET_PROTOSW_ICSK,
 };
 
+static char dccp_v6_ctl_socket_err_msg[] __initdata =
+       KERN_ERR "DCCP: Failed to create the control socket.\n";
+
+static int __init dccp_v6_ctl_sock_init(void)
+{
+       int rc = sock_create_kern(PF_INET6, SOCK_DCCP, IPPROTO_DCCP,
+                                 &dccp_v6_ctl_socket);
+       if (rc < 0)
+               printk(dccp_v6_ctl_socket_err_msg);
+       else {
+               dccp_v6_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
+               inet_sk(dccp_v6_ctl_socket->sk)->uc_ttl = -1;
+
+               /* Unhash it so that IP input processing does not even
+                * see it, we do not wish this socket to see incoming
+                * packets.
+                */
+               dccp_v6_ctl_socket->sk->sk_prot->unhash(dccp_v6_ctl_socket->sk);
+       }
+
+       return rc;
+}
+
 static int __init dccp_v6_init(void)
 {
        int err = proto_register(&dccp_v6_prot, 1);
@@ -1234,8 +1264,14 @@ static int __init dccp_v6_init(void)
                goto out_unregister_proto;
 
        inet6_register_protosw(&dccp_v6_protosw);
+
+       if (dccp_v6_ctl_sock_init() != 0)
+               goto out_unregister_protosw;
 out:
        return err;
+out_unregister_protosw:
+       inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+       inet6_unregister_protosw(&dccp_v6_protosw);
 out_unregister_proto:
        proto_unregister(&dccp_v6_prot);
        goto out;
index f644c1a23c4dce41e99d3b760ffff90986aa1356..baccaf35ffbda1129690b6271d544c08ed9c59d6 100644 (file)
@@ -163,11 +163,10 @@ void dccp_unhash(struct sock *sk)
 
 EXPORT_SYMBOL_GPL(dccp_unhash);
 
-int dccp_init_sock(struct sock *sk)
+int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct inet_connection_sock *icsk = inet_csk(sk);
-       static int dccp_ctl_socket_init = 1;
 
        dccp_options_init(&dp->dccps_options);
        do_gettimeofday(&dp->dccps_epoch);
@@ -179,7 +178,7 @@ int dccp_init_sock(struct sock *sk)
         * lets leave it here, later the real solution is to do this in a
         * setsockopt(CCIDs-I-want/accept). -acme
         */
-       if (likely(!dccp_ctl_socket_init)) {
+       if (likely(ctl_sock_initialized)) {
                int rc = dccp_feat_init(sk);
 
                if (rc)
@@ -211,7 +210,6 @@ int dccp_init_sock(struct sock *sk)
                /* 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);