Commit 3b11b57a authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

Merge kernel.bkbits.net:/home/jmorris/net-2.5

into linux-ipv6.org:/home/jmorris/bk/net/work-2.5
parents 67c62753 452b9318
...@@ -101,6 +101,8 @@ struct frag_hdr { ...@@ -101,6 +101,8 @@ struct frag_hdr {
__u32 identification; __u32 identification;
}; };
#define IP6_MF 0x0001
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <net/sock.h> #include <net/sock.h>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/in6.h> #include <linux/in6.h>
#include <linux/route.h> #include <linux/route.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h> #include <net/sock.h>
...@@ -554,66 +555,132 @@ int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen) ...@@ -554,66 +555,132 @@ int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct ip6fl_iter_state {
int bucket;
};
static int ip6_fl_read_proc(char *buffer, char **start, off_t offset, #define ip6fl_seq_private(seq) ((struct ip6fl_iter_state *)&(seq)->private)
int length, int *eof, void *data)
{
off_t pos=0;
off_t begin=0;
int len=0;
int i, k;
struct ip6_flowlabel *fl;
len+= sprintf(buffer,"Label S Owner Users Linger Expires " static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
"Dst Opt\n"); {
struct ip6_flowlabel *fl = NULL;
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
read_lock_bh(&ip6_fl_lock); for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) {
for (i=0; i<=FL_HASH_MASK; i++) { if (fl_ht[state->bucket]) {
for (fl = fl_ht[i]; fl; fl = fl->next) { fl = fl_ht[state->bucket];
len+=sprintf(buffer+len,"%05X %-1d %-6d %-6d %-6d %-8ld ", break;
(unsigned)ntohl(fl->label),
fl->share,
(unsigned)fl->owner,
atomic_read(&fl->users),
fl->linger/HZ,
(long)(fl->expires - jiffies)/HZ);
for (k=0; k<16; k++)
len+=sprintf(buffer+len, "%02x", fl->dst.s6_addr[k]);
buffer[len++]=' ';
len+=sprintf(buffer+len, "%-4d", fl->opt ? fl->opt->opt_nflen : 0);
buffer[len++]='\n';
pos=begin+len;
if(pos<offset) {
len=0;
begin=pos;
}
if(pos>offset+length)
goto done;
} }
} }
*eof = 1; return fl;
}
done: static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl)
{
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
fl = fl->next;
while (!fl) {
if (++state->bucket <= FL_HASH_MASK)
fl = fl_ht[state->bucket];
}
return fl;
}
static struct ip6_flowlabel *ip6fl_get_idx(struct seq_file *seq, loff_t pos)
{
struct ip6_flowlabel *fl = ip6fl_get_first(seq);
if (fl)
while (pos && (fl = ip6fl_get_next(seq, fl)) != NULL)
--pos;
return pos ? NULL : fl;
}
static void *ip6fl_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock_bh(&ip6_fl_lock);
return *pos ? ip6fl_get_idx(seq, *pos) : (void *)1;
}
static void *ip6fl_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct ip6_flowlabel *fl;
if (v == (void *)1)
fl = ip6fl_get_first(seq);
else
fl = ip6fl_get_next(seq, v);
++*pos;
return fl;
}
static void ip6fl_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&ip6_fl_lock); read_unlock_bh(&ip6_fl_lock);
*start=buffer+(offset-begin);
len-=(offset-begin);
if(len>length)
len=length;
if(len<0)
len=0;
return len;
} }
static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
{
while(fl) {
seq_printf(seq,
"%05X %-1d %-6d %-6d %-6d %-8ld "
"%02x%02x%02x%02x%02x%02x%02x%02x "
"%-4d\n",
(unsigned)ntohl(fl->label),
fl->share,
(unsigned)fl->owner,
atomic_read(&fl->users),
fl->linger/HZ,
(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 == (void *)1)
seq_printf(seq, "Label S Owner Users Linger Expires "
"Dst Opt\n");
else
ip6fl_fl_seq_show(seq, v);
return 0;
}
static struct seq_operations ip6fl_seq_ops = {
.start = ip6fl_seq_start,
.next = ip6fl_seq_next,
.stop = ip6fl_seq_stop,
.show = ip6fl_seq_show,
};
static int ip6fl_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &ip6fl_seq_ops);
}
static struct file_operations ip6fl_seq_fops = {
.owner = THIS_MODULE,
.open = ip6fl_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#endif #endif
void ip6_flowlabel_init() void ip6_flowlabel_init()
{ {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *p;
#endif
init_timer(&ip6_fl_gc_timer); init_timer(&ip6_fl_gc_timer);
ip6_fl_gc_timer.function = ip6_fl_gc; ip6_fl_gc_timer.function = ip6_fl_gc;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
create_proc_read_entry("net/ip6_flowlabel", 0, 0, ip6_fl_read_proc, NULL); p = create_proc_entry("ip6_flowlabel", S_IRUGO, proc_net);
if (p)
p->proc_fops = &ip6fl_seq_fops;
#endif #endif
} }
...@@ -621,6 +688,6 @@ void ip6_flowlabel_cleanup() ...@@ -621,6 +688,6 @@ void ip6_flowlabel_cleanup()
{ {
del_timer(&ip6_fl_gc_timer); del_timer(&ip6_fl_gc_timer);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
remove_proc_entry("net/ip6_flowlabel", 0); proc_net_remove("ip6_flowlabel");
#endif #endif
} }
...@@ -984,7 +984,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -984,7 +984,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
ipv6_select_ident(skb, fh); ipv6_select_ident(skb, fh);
fh->nexthdr = nexthdr; fh->nexthdr = nexthdr;
fh->reserved = 0; fh->reserved = 0;
fh->frag_off = htons(0x0001); fh->frag_off = htons(IP6_MF);
frag_id = fh->identification; frag_id = fh->identification;
first_len = skb_pagelen(skb); first_len = skb_pagelen(skb);
...@@ -1004,9 +1004,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -1004,9 +1004,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
offset += skb->len - hlen - sizeof(struct frag_hdr); offset += skb->len - hlen - sizeof(struct frag_hdr);
fh->nexthdr = nexthdr; fh->nexthdr = nexthdr;
fh->reserved = 0; fh->reserved = 0;
if (frag->next != NULL)
offset |= 0x0001;
fh->frag_off = htons(offset); fh->frag_off = htons(offset);
if (frag->next != NULL)
fh->frag_off |= htons(IP6_MF);
fh->identification = frag_id; fh->identification = frag_id;
frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
ip6_copy_metadata(frag, skb); ip6_copy_metadata(frag, skb);
...@@ -1113,7 +1113,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -1113,7 +1113,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
BUG(); BUG();
left -= len; left -= len;
fh->frag_off = htons( left > 0 ? (offset | 0x0001) : offset); fh->frag_off = htons(offset);
if (left > 0)
fh->frag_off |= htons(IP6_MF);
frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
ptr += len; ptr += len;
......
...@@ -435,7 +435,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -435,7 +435,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0)); csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0));
/* Is this the final fragment? */ /* Is this the final fragment? */
if (!(fhdr->frag_off & htons(0x0001))) { if (!(fhdr->frag_off & htons(IP6_MF))) {
/* If we already have some bits beyond end /* If we already have some bits beyond end
* or have different end, the segment is corrupted. * or have different end, the segment is corrupted.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment