]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sctp/protocol.c
sched: fix memory leak in a failure path
[linux-2.6-omap-h63xx.git] / net / sctp / protocol.c
index 98c6a882016a397947c5b0403212fb91ecbd5933..0b65354aaf64978a68836f1cb9754e4101cbc35b 100644 (file)
@@ -52,6 +52,8 @@
 #include <linux/inetdevice.h>
 #include <linux/seq_file.h>
 #include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/swap.h>
 #include <net/net_namespace.h>
 #include <net/protocol.h>
 #include <net/ip.h>
 
 /* Global data structures. */
 struct sctp_globals sctp_globals __read_mostly;
-struct proc_dir_entry  *proc_net_sctp;
 DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
 
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry  *proc_net_sctp;
+#endif
+
 struct idr sctp_assocs_id;
 DEFINE_SPINLOCK(sctp_assocs_id_lock);
 
@@ -97,6 +102,7 @@ struct sock *sctp_get_ctl_sock(void)
 /* Set up the proc fs entry for the SCTP protocol. */
 static __init int sctp_proc_init(void)
 {
+#ifdef CONFIG_PROC_FS
        if (!proc_net_sctp) {
                struct proc_dir_entry *ent;
                ent = proc_mkdir("sctp", init_net.proc_net);
@@ -131,6 +137,9 @@ out_snmp_proc_init:
        }
 out_nomem:
        return -ENOMEM;
+#else
+       return 0;
+#endif /* CONFIG_PROC_FS */
 }
 
 /* Clean up the proc fs entry for the SCTP protocol.
@@ -139,6 +148,7 @@ out_nomem:
  */
 static void sctp_proc_exit(void)
 {
+#ifdef CONFIG_PROC_FS
        sctp_snmp_proc_exit();
        sctp_eps_proc_exit();
        sctp_assocs_proc_exit();
@@ -148,6 +158,7 @@ static void sctp_proc_exit(void)
                proc_net_sctp = NULL;
                remove_proc_entry("sctp", init_net.proc_net);
        }
+#endif
 }
 
 /* Private helper to extract ipv4 address and stash them in
@@ -372,6 +383,10 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
                              struct sctp_sock *sp,
                              const struct sk_buff *skb)
 {
+       /* IPv4 addresses not allowed */
+       if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
+               return 0;
+
        /* Is this a non-unicast address or a unusable SCTP address? */
        if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr))
                return 0;
@@ -395,6 +410,9 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
           !sysctl_ip_nonlocal_bind)
                return 0;
 
+       if (ipv6_only_sock(sctp_opt2sk(sp)))
+               return 0;
+
        return 1;
 }
 
@@ -650,7 +668,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
        struct sctp_sockaddr_entry *temp;
        int found = 0;
 
-       if (dev_net(ifa->ifa_dev->dev) != &init_net)
+       if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
                return NOTIFY_DONE;
 
        switch (ev) {
@@ -844,16 +862,21 @@ static int sctp_inet_supported_addrs(const struct sctp_sock *opt,
 
 /* Wrapper routine that calls the ip transmit routine. */
 static inline int sctp_v4_xmit(struct sk_buff *skb,
-                              struct sctp_transport *transport, int ipfragok)
+                              struct sctp_transport *transport)
 {
+       struct inet_sock *inet = inet_sk(skb->sk);
+
        SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
                          "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
                          __func__, skb, skb->len,
                          NIPQUAD(skb->rtable->rt_src),
                          NIPQUAD(skb->rtable->rt_dst));
 
+       inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
+                        IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
+
        SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
-       return ip_queue_xmit(skb, ipfragok);
+       return ip_queue_xmit(skb, 0);
 }
 
 static struct sctp_af sctp_af_inet;
@@ -1064,6 +1087,7 @@ SCTP_STATIC __init int sctp_init(void)
        int status = -EINVAL;
        unsigned long goal;
        unsigned long limit;
+       unsigned long nr_pages;
        int max_share;
        int order;
 
@@ -1159,8 +1183,9 @@ SCTP_STATIC __init int sctp_init(void)
         * Note this initalizes the data in sctpv6_prot too
         * Unabashedly stolen from tcp_init
         */
-       limit = min(num_physpages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
-       limit = (limit * (num_physpages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
+       nr_pages = totalram_pages - totalhigh_pages;
+       limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
+       limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
        limit = max(limit, 128UL);
        sysctl_sctp_mem[0] = limit / 4 * 3;
        sysctl_sctp_mem[1] = limit;
@@ -1170,7 +1195,7 @@ SCTP_STATIC __init int sctp_init(void)
        limit = (sysctl_sctp_mem[1]) << (PAGE_SHIFT - 7);
        max_share = min(4UL*1024*1024, limit);
 
-       sysctl_sctp_rmem[0] = PAGE_SIZE; /* give each asoc 1 page min */
+       sysctl_sctp_rmem[0] = SK_MEM_QUANTUM; /* give each asoc 1 page min */
        sysctl_sctp_rmem[1] = (1500 *(sizeof(struct sk_buff) + 1));
        sysctl_sctp_rmem[2] = max(sysctl_sctp_rmem[1], max_share);