12 #include <linux/capability.h>
13 #include <linux/errno.h>
14 #include <linux/types.h>
15 #include <linux/socket.h>
16 #include <linux/net.h>
17 #include <linux/netdevice.h>
18 #include <linux/if_arp.h>
19 #include <linux/in6.h>
23 #include <linux/slab.h>
24 #include <linux/export.h>
39 #include <asm/uaccess.h>
41 #define FL_MIN_LINGER 6
44 #define FL_MAX_LINGER 60
48 #define FL_MAX_PER_SOCK 32
49 #define FL_MAX_SIZE 4096
50 #define FL_HASH_MASK 255
51 #define FL_HASH(l) (ntohl(l)&FL_HASH_MASK)
56 static void ip6_fl_gc(
unsigned long dummy);
84 fl = __fl_lookup(net, label);
118 if (!timer_pending(&ip6_fl_gc_timer) ||
125 static void ip6_fl_gc(
unsigned long dummy)
129 unsigned long sched = 0;
136 while ((fl=*flp) !=
NULL) {
162 static void __net_exit ip6_fl_purge(
struct net *net)
170 while ((fl = *flp) !=
NULL) {
171 if (net_eq(fl->
fl_net, net) &&
196 lfl = __fl_lookup(net, fl->
label);
210 lfl = __fl_lookup(net, fl->
label);
240 if (fl->
label == label) {
283 if (fl_opt !=
NULL) {
302 static unsigned long check_linger(
unsigned long ttl)
311 static int fl6_renew(
struct ip6_flowlabel *fl,
unsigned long linger,
unsigned long expires)
313 linger = check_linger(linger);
316 expires = check_linger(expires);
331 char __user *optval,
int optlen,
int *err_p)
340 if (olen > 64 * 1024)
359 fl->
opt->tot_len =
sizeof(*fl->
opt) + olen;
364 msg.msg_controllen = olen;
365 msg.msg_control = (
void*)(fl->
opt+1);
373 if (fl->
opt->opt_flen)
375 if (fl->
opt->opt_nflen == 0) {
381 fl->
fl_net = hold_net(net);
387 addr_type = ipv6_addr_type(&freq->
flr_dst);
417 static int mem_check(
struct sock *sk)
447 return memcmp(h1+1, h2+1, ((h1->
hdrlen+1)<<3) -
sizeof(*h1));
480 struct net *net = sock_net(sk);
488 if (optlen <
sizeof(freq))
533 if (freq.
flr_label & ~IPV6_FLOWLABEL_MASK)
536 fl = fl_create(net, sk, &freq, optval, optlen, &err);
574 if (!ipv6_addr_equal(&fl1->
dst, &fl->
dst) ||
575 ipv6_opt_cmp(fl1->
opt, fl->
opt))
585 fl_link(np, sfl1, fl1);
599 if (sfl1 ==
NULL || (err = mem_check(sk)) != 0)
602 fl1 = fl_intern(net, fl, freq.
flr_label);
613 fl_link(np, sfl1, fl);
626 #ifdef CONFIG_PROC_FS
628 struct ip6fl_iter_state {
634 #define ip6fl_seq_private(seq) ((struct ip6fl_iter_state *)(seq)->private)
639 struct ip6fl_iter_state *
state = ip6fl_seq_private(seq);
640 struct net *net = seq_file_net(seq);
642 for (state->bucket = 0; state->bucket <=
FL_HASH_MASK; ++state->bucket) {
643 fl = fl_ht[state->bucket];
645 while (fl && !net_eq(fl->
fl_net, net))
655 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
656 struct net *net = seq_file_net(seq);
660 while (fl && !net_eq(fl->
fl_net, net))
665 fl = fl_ht[state->bucket];
677 while (pos && (fl = ip6fl_get_next(seq, fl)) !=
NULL)
682 static void *ip6fl_seq_start(
struct seq_file *seq, loff_t *pos)
689 static void *ip6fl_seq_next(
struct seq_file *seq,
void *
v, loff_t *pos)
694 fl = ip6fl_get_first(seq);
696 fl = ip6fl_get_next(seq, v);
701 static void ip6fl_seq_stop(
struct seq_file *seq,
void *v)
707 static int ip6fl_seq_show(
struct seq_file *seq,
void *v)
709 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
711 seq_printf(seq,
"%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
712 "Label",
"S",
"Owner",
"Users",
"Linger",
"Expires",
"Dst",
"Opt");
716 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n",
726 (
long)(fl->
expires - jiffies)/HZ,
728 fl->
opt ? fl->
opt->opt_nflen : 0);
734 .
start = ip6fl_seq_start,
735 .next = ip6fl_seq_next,
736 .stop = ip6fl_seq_stop,
737 .show = ip6fl_seq_show,
743 struct ip6fl_iter_state *
state;
747 sizeof(
struct ip6fl_iter_state));
751 state = ip6fl_seq_private(seq);
759 static int ip6fl_seq_release(
struct inode *inode,
struct file *file)
762 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
769 .open = ip6fl_seq_open,
772 .release = ip6fl_seq_release,
775 static int __net_init ip6_flowlabel_proc_init(
struct net *net)
783 static void __net_exit ip6_flowlabel_proc_fini(
struct net *net)
788 static inline int ip6_flowlabel_proc_init(
struct net *net)
792 static inline void ip6_flowlabel_proc_fini(
struct net *net)
797 static void __net_exit ip6_flowlabel_net_exit(
struct net *net)
800 ip6_flowlabel_proc_fini(net);
804 .init = ip6_flowlabel_proc_init,
805 .exit = ip6_flowlabel_net_exit,