* 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>
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;
return NULL;
}
-static struct ip6_flowlabel * fl_lookup(u32 label)
+static struct ip6_flowlabel * fl_lookup(__be32 label)
{
struct ip6_flowlabel *fl;
static void fl_free(struct ip6_flowlabel *fl)
{
- if (fl->opt)
+ if (fl)
kfree(fl->opt);
kfree(fl);
}
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;
/* 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);
return NULL;
}
+EXPORT_SYMBOL_GPL(fl6_sock_lookup);
+
void fl6_free_socklist(struct sock *sk)
{
struct ipv6_pinfo *np = inet6_sk(sk);
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;
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;
}
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) {
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;
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) {
return fl;
done:
- if (fl)
- fl_free(fl);
+ fl_free(fl);
*err_p = err;
return NULL;
}
goto done;
}
fl1 = sfl->fl;
- atomic_inc(&fl->users);
+ atomic_inc(&fl1->users);
break;
}
}
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;
if (err)
goto done;
- /* Do not check for fault */
- if (!freq.flr_label)
- copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
- &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;
}
done:
- if (fl)
- fl_free(fl);
- if (sfl1)
- kfree(sfl1);
+ fl_free(fl);
+ kfree(sfl1);
return err;
}
while (!fl) {
if (++state->bucket <= FL_HASH_MASK)
fl = fl_ht[state->bucket];
+ else
+ break;
}
return fl;
}
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,
(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_puts(seq, "Label S Owner Users Linger Expires "
- "Dst Opt\n");
- else
- ip6fl_fl_seq_show(seq, v);
return 0;
}
{
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;
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree: