]> err.no Git - linux-2.6/blobdiff - net/dccp/ipv4.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
[linux-2.6] / net / dccp / ipv4.c
index 033c3ab8fe331ddf9eaeeaa073d27c272351dca1..f2c011fd2ba128f92757aa816da604804d99394f 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,
@@ -190,11 +197,12 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
        } /* else let the usual retransmit timer handle it */
 }
 
-static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
+static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb,
+                                  struct request_sock *req)
 {
        int err;
        struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
-       const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
+       const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
                                     sizeof(struct dccp_hdr_ext) +
                                     sizeof(struct dccp_hdr_ack_bits);
        struct sk_buff *skb;
@@ -202,12 +210,12 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
        if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
                return;
 
-       skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC);
+       skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header, GFP_ATOMIC);
        if (skb == NULL)
                return;
 
        /* Reserve space for headers. */
-       skb_reserve(skb, MAX_DCCP_HEADER);
+       skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
 
        skb->dst = dst_clone(rxskb->dst);
 
@@ -226,11 +234,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);
@@ -238,12 +246,6 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
        }
 }
 
-static void dccp_v4_reqsk_send_ack(struct sk_buff *skb,
-                                  struct request_sock *req)
-{
-       dccp_v4_ctl_send_ack(skb);
-}
-
 static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
                                 struct dst_entry *dst)
 {
@@ -496,7 +498,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                goto drop;
 
        if (dccp_parse_options(sk, skb))
-               goto drop;
+               goto drop_and_free;
 
        dccp_openreq_init(req, &dp, skb);
 
@@ -704,16 +706,17 @@ 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;
 
-       skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC);
+       skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header,
+                       GFP_ATOMIC);
        if (skb == NULL)
                goto out;
 
        /* Reserve space for headers. */
-       skb_reserve(skb, MAX_DCCP_HEADER);
+       skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
        skb->dst = dst_clone(dst);
 
        skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
@@ -741,11 +744,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);
@@ -983,24 +986,33 @@ do_time_wait:
 }
 
 static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
-       .queue_xmit     = ip_queue_xmit,
-       .send_check     = dccp_v4_send_check,
-       .rebuild_header = inet_sk_rebuild_header,
-       .conn_request   = dccp_v4_conn_request,
-       .syn_recv_sock  = dccp_v4_request_recv_sock,
-       .net_header_len = sizeof(struct iphdr),
-       .setsockopt     = ip_setsockopt,
-       .getsockopt     = ip_getsockopt,
-       .addr2sockaddr  = inet_csk_addr2sockaddr,
-       .sockaddr_len   = sizeof(struct sockaddr_in),
+       .queue_xmit        = ip_queue_xmit,
+       .send_check        = dccp_v4_send_check,
+       .rebuild_header    = inet_sk_rebuild_header,
+       .conn_request      = dccp_v4_conn_request,
+       .syn_recv_sock     = dccp_v4_request_recv_sock,
+       .net_header_len    = sizeof(struct iphdr),
+       .setsockopt        = ip_setsockopt,
+       .getsockopt        = ip_getsockopt,
+       .addr2sockaddr     = inet_csk_addr2sockaddr,
+       .sockaddr_len      = sizeof(struct sockaddr_in),
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt = compat_ip_setsockopt,
+       .compat_getsockopt = compat_ip_getsockopt,
+#endif
 };
 
 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;
 }
 
@@ -1022,7 +1034,7 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
        .twsk_obj_size  = sizeof(struct inet_timewait_sock),
 };
 
-struct proto dccp_v4_prot = {
+static struct proto dccp_v4_prot = {
        .name                   = "DCCP",
        .owner                  = THIS_MODULE,
        .close                  = dccp_close,
@@ -1046,6 +1058,10 @@ struct proto dccp_v4_prot = {
        .obj_size               = sizeof(struct dccp_sock),
        .rsk_prot               = &dccp_request_sock_ops,
        .twsk_prot              = &dccp_timewait_sock_ops,
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt      = compat_dccp_setsockopt,
+       .compat_getsockopt      = compat_dccp_getsockopt,
+#endif
 };
 
 static struct net_protocol dccp_v4_protocol = {
@@ -1055,26 +1071,30 @@ static struct net_protocol dccp_v4_protocol = {
 };
 
 static const struct proto_ops inet_dccp_ops = {
-       .family         = PF_INET,
-       .owner          = THIS_MODULE,
-       .release        = inet_release,
-       .bind           = inet_bind,
-       .connect        = inet_stream_connect,
-       .socketpair     = sock_no_socketpair,
-       .accept         = inet_accept,
-       .getname        = inet_getname,
+       .family            = PF_INET,
+       .owner             = THIS_MODULE,
+       .release           = inet_release,
+       .bind              = inet_bind,
+       .connect           = inet_stream_connect,
+       .socketpair        = sock_no_socketpair,
+       .accept            = inet_accept,
+       .getname           = inet_getname,
        /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
-       .poll           = dccp_poll,
-       .ioctl          = inet_ioctl,
+       .poll              = dccp_poll,
+       .ioctl             = inet_ioctl,
        /* FIXME: work on inet_listen to rename it to sock_common_listen */
-       .listen         = inet_dccp_listen,
-       .shutdown       = inet_shutdown,
-       .setsockopt     = sock_common_setsockopt,
-       .getsockopt     = sock_common_getsockopt,
-       .sendmsg        = inet_sendmsg,
-       .recvmsg        = sock_common_recvmsg,
-       .mmap           = sock_no_mmap,
-       .sendpage       = sock_no_sendpage,
+       .listen            = inet_dccp_listen,
+       .shutdown          = inet_shutdown,
+       .setsockopt        = sock_common_setsockopt,
+       .getsockopt        = sock_common_getsockopt,
+       .sendmsg           = inet_sendmsg,
+       .recvmsg           = sock_common_recvmsg,
+       .mmap              = sock_no_mmap,
+       .sendpage          = sock_no_sendpage,
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt = compat_sock_common_setsockopt,
+       .compat_getsockopt = compat_sock_common_getsockopt,
+#endif
 };
 
 static struct inet_protosw dccp_v4_protosw = {
@@ -1087,48 +1107,6 @@ 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 =
-       KERN_ERR "DCCP: Failed to create the control socket.\n";
-
-static int __init dccp_ctl_sock_init(void)
-{
-       int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
-                                 &dccp_ctl_socket);
-       if (rc < 0)
-               printk(dccp_ctl_socket_err_msg);
-       else {
-               dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
-               inet_sk(dccp_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);
-       }
-
-       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 +1120,8 @@ static int __init dccp_v4_init(void)
 
        inet_register_protosw(&dccp_v4_protosw);
 
-       err = dccp_ctl_sock_init();
+       err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET,
+                                      SOCK_DCCP, IPPROTO_DCCP);
        if (err)
                goto out_unregister_protosw;
 out: