nfsd: simplify fh_verify access checks
[safe/jmp/linux-2.6] / net / sctp / protocol.c
index 4e66384..612dc87 100644 (file)
@@ -106,12 +106,8 @@ static __init int sctp_proc_init(void)
                goto out_nomem;
 #ifdef CONFIG_PROC_FS
        if (!proc_net_sctp) {
-               struct proc_dir_entry *ent;
-               ent = proc_mkdir("sctp", init_net.proc_net);
-               if (ent) {
-                       ent->owner = THIS_MODULE;
-                       proc_net_sctp = ent;
-               } else
+               proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
+               if (!proc_net_sctp)
                        goto out_free_percpu;
        }
 
@@ -164,6 +160,7 @@ static void sctp_proc_exit(void)
                remove_proc_entry("sctp", init_net.proc_net);
        }
 #endif
+       percpu_counter_destroy(&sctp_sockets_allocated);
 }
 
 /* Private helper to extract ipv4 address and stash them in
@@ -397,7 +394,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
                return 0;
 
        /* Is this a broadcast address? */
-       if (skb && skb->rtable->rt_flags & RTCF_BROADCAST)
+       if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST)
                return 0;
 
        return 1;
@@ -434,16 +431,14 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
  * of requested destination address, sender and receiver
  * SHOULD include all of its addresses with level greater
  * than or equal to L.
+ *
+ * IPv4 scoping can be controlled through sysctl option
+ * net.sctp.addr_scope_policy
  */
 static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
 {
        sctp_scope_t retval;
 
-       /* Should IPv4 scoping be a sysctl configurable option
-        * so users can turn it off (default on) for certain
-        * unconventional networking environments?
-        */
-
        /* Check for unusable SCTP addresses. */
        if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) {
                retval =  SCTP_SCOPE_UNUSABLE;
@@ -576,7 +571,7 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk,
 /* What interface did this skb arrive on? */
 static int sctp_v4_skb_iif(const struct sk_buff *skb)
 {
-       return skb->rtable->rt_iif;
+       return skb_rtable(skb)->rt_iif;
 }
 
 /* Was this packet marked by Explicit Congestion Notification? */
@@ -589,46 +584,21 @@ static int sctp_v4_is_ce(const struct sk_buff *skb)
 static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
                                             struct sctp_association *asoc)
 {
-       struct inet_sock *inet = inet_sk(sk);
-       struct inet_sock *newinet;
        struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
                        sk->sk_prot);
+       struct inet_sock *newinet;
 
        if (!newsk)
                goto out;
 
        sock_init_data(NULL, newsk);
 
-       newsk->sk_type = SOCK_STREAM;
-
-       newsk->sk_no_check = sk->sk_no_check;
-       newsk->sk_reuse = sk->sk_reuse;
-       newsk->sk_shutdown = sk->sk_shutdown;
-
-       newsk->sk_destruct = inet_sock_destruct;
-       newsk->sk_family = PF_INET;
-       newsk->sk_protocol = IPPROTO_SCTP;
-       newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+       sctp_copy_sock(newsk, sk, asoc);
        sock_reset_flag(newsk, SOCK_ZAPPED);
 
        newinet = inet_sk(newsk);
 
-       /* Initialize sk's sport, dport, rcv_saddr and daddr for
-        * getsockname() and getpeername()
-        */
-       newinet->sport = inet->sport;
-       newinet->saddr = inet->saddr;
-       newinet->rcv_saddr = inet->rcv_saddr;
-       newinet->dport = htons(asoc->peer.port);
        newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
-       newinet->pmtudisc = inet->pmtudisc;
-       newinet->id = asoc->next_tsn ^ jiffies;
-
-       newinet->uc_ttl = -1;
-       newinet->mc_loop = 1;
-       newinet->mc_ttl = 1;
-       newinet->mc_index = 0;
-       newinet->mc_list = NULL;
 
        sk_refcnt_debug_inc(newsk);
 
@@ -717,15 +687,20 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 static int sctp_ctl_sock_init(void)
 {
        int err;
-       sa_family_t family;
+       sa_family_t family = PF_INET;
 
        if (sctp_get_pf_specific(PF_INET6))
                family = PF_INET6;
-       else
-               family = PF_INET;
 
        err = inet_ctl_sock_create(&sctp_ctl_sock, family,
                                   SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
+
+       /* If IPv6 socket could not be created, try the IPv4 socket */
+       if (err < 0 && family == PF_INET6)
+               err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
+                                          SOCK_SEQPACKET, IPPROTO_SCTP,
+                                          &init_net);
+
        if (err < 0) {
                printk(KERN_ERR
                       "SCTP: Failed to create the SCTP control socket.\n");
@@ -872,8 +847,8 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
 
        SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n",
                          __func__, skb, skb->len,
-                         &skb->rtable->rt_src,
-                         &skb->rtable->rt_dst);
+                         &skb_rtable(skb)->rt_src,
+                         &skb_rtable(skb)->rt_dst);
 
        inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
                         IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
@@ -949,7 +924,7 @@ static struct inet_protosw sctp_stream_protosw = {
 };
 
 /* Register with IP layer.  */
-static struct net_protocol sctp_protocol = {
+static const struct net_protocol sctp_protocol = {
        .handler     = sctp_rcv,
        .err_handler = sctp_v4_err,
        .no_policy   = 1,
@@ -1209,10 +1184,10 @@ SCTP_STATIC __init int sctp_init(void)
        /* Size and allocate the association hash table.
         * The methodology is similar to that of the tcp hash tables.
         */
-       if (num_physpages >= (128 * 1024))
-               goal = num_physpages >> (22 - PAGE_SHIFT);
+       if (totalram_pages >= (128 * 1024))
+               goal = totalram_pages >> (22 - PAGE_SHIFT);
        else
-               goal = num_physpages >> (24 - PAGE_SHIFT);
+               goal = totalram_pages >> (24 - PAGE_SHIFT);
 
        for (order = 0; (1UL << order) < goal; order++)
                ;
@@ -1282,6 +1257,9 @@ SCTP_STATIC __init int sctp_init(void)
        /* Disable AUTH by default. */
        sctp_auth_enable = 0;
 
+       /* Set SCOPE policy to enabled */
+       sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
+
        sctp_sysctl_register();
 
        INIT_LIST_HEAD(&sctp_address_families);
@@ -1394,6 +1372,8 @@ SCTP_STATIC __exit void sctp_exit(void)
        sctp_proc_exit();
        cleanup_sctp_mibs();
 
+       rcu_barrier(); /* Wait for completion of call_rcu()'s */
+
        kmem_cache_destroy(sctp_chunk_cachep);
        kmem_cache_destroy(sctp_bucket_cachep);
 }
@@ -1408,4 +1388,6 @@ MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
 MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132");
 MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
 MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
+module_param_named(no_checksums, sctp_checksum_disable, bool, 0644);
+MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification");
 MODULE_LICENSE("GPL");