fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / ipv6 / ip6_flowlabel.c
index 5c885fa..624fae2 100644 (file)
@@ -9,7 +9,7 @@
  *     Authors:        Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  */
 
-#include <linux/config.h>
+#include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -50,18 +50,18 @@ static atomic_t fl_size = ATOMIC_INIT(0);
 static struct ip6_flowlabel *fl_ht[FL_HASH_MASK+1];
 
 static void ip6_fl_gc(unsigned long dummy);
-static struct timer_list ip6_fl_gc_timer = TIMER_INITIALIZER(ip6_fl_gc, 0, 0);
+static DEFINE_TIMER(ip6_fl_gc_timer, ip6_fl_gc, 0, 0);
 
 /* FL hash table lock: it protects only of GC */
 
-static rwlock_t ip6_fl_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ip6_fl_lock);
 
 /* Big socket sock */
 
-static rwlock_t ip6_sk_fl_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ip6_sk_fl_lock);
 
 
-static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label)
+static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label)
 {
        struct ip6_flowlabel *fl;
 
@@ -72,7 +72,7 @@ static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label)
        return NULL;
 }
 
-static struct ip6_flowlabel * fl_lookup(u32 label)
+static struct ip6_flowlabel * fl_lookup(__be32 label)
 {
        struct ip6_flowlabel *fl;
 
@@ -87,7 +87,7 @@ static struct ip6_flowlabel * fl_lookup(u32 label)
 
 static void fl_free(struct ip6_flowlabel *fl)
 {
-       if (fl->opt)
+       if (fl)
                kfree(fl->opt);
        kfree(fl);
 }
@@ -153,7 +153,7 @@ static void ip6_fl_gc(unsigned long dummy)
        write_unlock(&ip6_fl_lock);
 }
 
-static int fl_intern(struct ip6_flowlabel *fl, __u32 label)
+static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
 {
        fl->label = label & IPV6_FLOWLABEL_MASK;
 
@@ -182,7 +182,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __u32 label)
 
 /* Socket flowlabel lists */
 
-struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label)
+struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label)
 {
        struct ipv6_fl_socklist *sfl;
        struct ipv6_pinfo *np = inet6_sk(sk);
@@ -200,6 +200,8 @@ struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label)
        return NULL;
 }
 
+EXPORT_SYMBOL_GPL(fl6_sock_lookup);
+
 void fl6_free_socklist(struct sock *sk)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
@@ -226,10 +228,10 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
                                         struct ipv6_txoptions * fopt)
 {
        struct ipv6_txoptions * fl_opt = fl->opt;
-
+       
        if (fopt == NULL || fopt->opt_flen == 0)
                return fl_opt;
-
+       
        if (fl_opt != NULL) {
                opt_space->hopopt = fl_opt->hopopt;
                opt_space->dst0opt = fl_opt->dst0opt;
@@ -244,7 +246,6 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
                opt_space->opt_nflen = 0;
        }
        opt_space->dst1opt = fopt->dst1opt;
-       opt_space->auth = fopt->auth;
        opt_space->opt_flen = fopt->opt_flen;
        return opt_space;
 }
@@ -285,10 +286,9 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
        int err;
 
        err = -ENOMEM;
-       fl = kmalloc(sizeof(*fl), GFP_KERNEL);
+       fl = kzalloc(sizeof(*fl), GFP_KERNEL);
        if (fl == NULL)
                goto done;
-       memset(fl, 0, sizeof(*fl));
 
        olen = optlen - CMSG_ALIGN(sizeof(*freq));
        if (olen > 0) {
@@ -311,7 +311,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
                msg.msg_control = (void*)(fl->opt+1);
                flowi.oif = 0;
 
-               err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk);
+               err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk);
                if (err)
                        goto done;
                err = -EINVAL;
@@ -330,8 +330,10 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
        fl->share = freq->flr_share;
        addr_type = ipv6_addr_type(&freq->flr_dst);
        if ((addr_type&IPV6_ADDR_MAPPED)
-           || addr_type == IPV6_ADDR_ANY)
+           || addr_type == IPV6_ADDR_ANY) {
+               err = -EINVAL;
                goto done;
+       }
        ipv6_addr_copy(&fl->dst, &freq->flr_dst);
        atomic_set(&fl->users, 1);
        switch (fl->share) {
@@ -351,8 +353,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
        return fl;
 
 done:
-       if (fl)
-               fl_free(fl);
+       fl_free(fl);
        *err_p = err;
        return NULL;
 }
@@ -481,7 +482,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                                                goto done;
                                        }
                                        fl1 = sfl->fl;
-                                       atomic_inc(&fl->users);
+                                       atomic_inc(&fl1->users);
                                        break;
                                }
                        }
@@ -500,7 +501,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                                        goto release;
 
                                err = -EINVAL;
-                               if (ipv6_addr_cmp(&fl1->dst, &fl->dst) ||
+                               if (!ipv6_addr_equal(&fl1->dst, &fl->dst) ||
                                    ipv6_opt_cmp(fl1->opt, fl->opt))
                                        goto release;
 
@@ -536,9 +537,12 @@ release:
                if (err)
                        goto done;
 
-               /* Do not check for fault */
-               if (!freq.flr_label)
-                       copy_to_user(optval + ((u8*)&freq.flr_label - (u8*)&freq), &fl->label, sizeof(fl->label));
+               if (!freq.flr_label) {
+                       if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
+                                        &fl->label, sizeof(fl->label))) {
+                               /* Intentionally ignore fault. */
+                       }
+               }
 
                sfl1->fl = fl;
                sfl1->next = np->ipv6_fl_list;
@@ -550,10 +554,8 @@ release:
        }
 
 done:
-       if (fl)
-               fl_free(fl);
-       if (sfl1)
-               kfree(sfl1);
+       fl_free(fl);
+       kfree(sfl1);
        return err;
 }
 
@@ -587,6 +589,8 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo
        while (!fl) {
                if (++state->bucket <= FL_HASH_MASK)
                        fl = fl_ht[state->bucket];
+               else
+                       break;
        }
        return fl;
 }
@@ -623,13 +627,15 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
        read_unlock_bh(&ip6_fl_lock);
 }
 
-static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
+static int ip6fl_seq_show(struct seq_file *seq, void *v)
 {
-       while(fl) {
+       if (v == SEQ_START_TOKEN)
+               seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
+                          "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
+       else {
+               struct ip6_flowlabel *fl = v;
                seq_printf(seq,
-                          "%05X %-1d %-6d %-6d %-6ld %-8ld "
-                          "%02x%02x%02x%02x%02x%02x%02x%02x "
-                          "%-4d\n",
+                          "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
                           (unsigned)ntohl(fl->label),
                           fl->share,
                           (unsigned)fl->owner,
@@ -638,17 +644,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
                           (long)(fl->expires - jiffies)/HZ,
                           NIP6(fl->dst),
                           fl->opt ? fl->opt->opt_nflen : 0);
-               fl = fl->next;
        }
-}
-
-static int ip6fl_seq_show(struct seq_file *seq, void *v)
-{
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "Label S Owner  Users  Linger Expires  "
-                               "Dst                              Opt\n");
-       else
-               ip6fl_fl_seq_show(seq, v);
        return 0;
 }
 
@@ -663,7 +659,7 @@ static int ip6fl_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
-       struct ip6fl_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       struct ip6fl_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
 
        if (!s)
                goto out;
@@ -674,7 +670,6 @@ static int ip6fl_seq_open(struct inode *inode, struct file *file)
 
        seq = file->private_data;
        seq->private = s;
-       memset(s, 0, sizeof(*s));
 out:
        return rc;
 out_kfree: