[PATCH] (linux-2.6.0-test7) fix missing connections in /proc/net/tcp ("netstat -n -t -a")

From: Tim Shepard
Date: Tue Oct 14 2003 - 10:47:14 EST



I'm running linux-2.6.0-test7 and I have just found and fixed a bug
that was causing "netstat -n -t" to fail to display all of the
relevant connections (in some cases). The bug can be demonstrated by
noticing that

dd if=/proc/net/tcp bs=128k of=/tmp/tcp.big

returns more lines into the output file than does

dd if=/proc/net/tcp bs=1k of=/tmp/tcp.1k

which is using the same size read buffer that /bin/netstat uses.

(Note, the first number on each line read from /proc/net/tcp is crazy
on a linux-2.6.0-test7 kernel, and I will in a few moments send
another patch along to address that. But fixing *this* bug is
much more important than fixing that bug.)

Triggering this bug depends on having enough TCP sockets in LISTEN (I
believe 8 is sufficient) and you may have to create a few more TCP
connections and/or transition some to TIMEWAIT (by closing them) to be
able to see the bug. The bug is most easily seen on a system where
you know exactly what TCP connections you have open and in time-wait
and can spot the descrepency in the output from "netstat -n -t".


Patch is below. The problem is that listening_get_idx was not
decrementing *pos exactly the same number of times that it cdr'd down
the list.

The change to established_get_idx is not necessary to fix the bug,
but does keep it in sync with listening_get_idx.

I hope this is helpful and that that I have properly submitted this patch.
I welcome any comments.

-Tim Shepard
shep@xxxxxxxxxxxx


--- ../pristine/linux-2.6.0-test7/net/ipv4/tcp_ipv4.c 2003-10-08 15:24:03.000000000 -0400
+++ net/ipv4/tcp_ipv4.c 2003-10-13 17:33:09.000000000 -0400
@@ -2233,14 +2233,15 @@

static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
{
void *rc = listening_get_first(seq);

- if (rc)
- while (*pos && (rc = listening_get_next(seq, rc)))
- --*pos;
- return *pos ? NULL : rc;
+ while (rc && *pos) {
+ rc = listening_get_next(seq, rc);
+ --*pos;
+ }
+ return rc;
}

static void *established_get_first(struct seq_file *seq)
{
struct tcp_iter_state* st = seq->private;
@@ -2325,14 +2326,15 @@

static void *established_get_idx(struct seq_file *seq, loff_t pos)
{
void *rc = established_get_first(seq);

- if (rc)
- while (pos && (rc = established_get_next(seq, rc)))
- --pos;
- return pos ? NULL : rc;
+ while (rc && pos) {
+ rc = established_get_next(seq, rc);
+ --pos;
+ }
+ return rc;
}

static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
{
void *rc;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/