Commit c31ba884 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[NET]: /proc/net/if_inet6 may drop some data.

parent 96d35d15
...@@ -2149,59 +2149,65 @@ struct if6_iter_state { ...@@ -2149,59 +2149,65 @@ struct if6_iter_state {
int bucket; int bucket;
}; };
static inline struct inet6_ifaddr *if6_get_bucket(struct seq_file *seq, loff_t *pos) static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
{ {
int i;
struct inet6_ifaddr *ifa = NULL; struct inet6_ifaddr *ifa = NULL;
loff_t l = *pos;
struct if6_iter_state *state = seq->private; struct if6_iter_state *state = seq->private;
for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
for (i = 0, ifa = inet6_addr_lst[state->bucket]; ifa; ++i, ifa=ifa->lst_next) { ifa = inet6_addr_lst[state->bucket];
if (l--) if (ifa)
continue; break;
*pos = i; }
goto out; return ifa;
}
static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
{
struct if6_iter_state *state = seq->private;
ifa = ifa->lst_next;
try_again:
if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) {
ifa = inet6_addr_lst[state->bucket];
goto try_again;
} }
out:
return ifa; return ifa;
} }
static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos)
{
struct inet6_ifaddr *ifa = if6_get_first(seq);
if (ifa)
while(pos && (ifa = if6_get_next(seq, ifa)) != NULL)
--pos;
return pos ? NULL : ifa;
}
static void *if6_seq_start(struct seq_file *seq, loff_t *pos) static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
{ {
read_lock_bh(&addrconf_hash_lock); read_lock_bh(&addrconf_hash_lock);
return *pos ? if6_get_bucket(seq, pos) : SEQ_START_TOKEN; return if6_get_idx(seq, *pos);
} }
static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
struct inet6_ifaddr *ifa; struct inet6_ifaddr *ifa;
struct if6_iter_state *state;
if (v == SEQ_START_TOKEN) {
ifa = if6_get_bucket(seq, pos);
goto out;
}
state = seq->private;
ifa = v; ifa = if6_get_next(seq, v);
ifa = ifa->lst_next;
if (ifa)
goto out;
if (++state->bucket >= IN6_ADDR_HSIZE)
goto out;
*pos = 0;
ifa = if6_get_bucket(seq, pos);
out:
++*pos; ++*pos;
return ifa; return ifa;
} }
static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr *ifp) static void if6_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&addrconf_hash_lock);
}
static int if6_seq_show(struct seq_file *seq, void *v)
{ {
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
seq_printf(seq, seq_printf(seq,
"%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n",
NIP6(ifp->addr), NIP6(ifp->addr),
...@@ -2210,22 +2216,9 @@ static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr ...@@ -2210,22 +2216,9 @@ static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr
ifp->scope, ifp->scope,
ifp->flags, ifp->flags,
ifp->idev->dev->name); ifp->idev->dev->name);
}
static int if6_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
return 0;
else
if6_iface_seq_show(seq, v);
return 0; return 0;
} }
static void if6_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&addrconf_hash_lock);
}
static struct seq_operations if6_seq_ops = { static struct seq_operations if6_seq_ops = {
.start = if6_seq_start, .start = if6_seq_start,
.next = if6_seq_next, .next = if6_seq_next,
......
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