Blame SOURCES/net-tools-cycle.patch

e7a6f3
diff -up net-tools-2.0/lib/interface.c.cycle net-tools-2.0/lib/interface.c
e7a6f3
--- net-tools-2.0/lib/interface.c.cycle	2016-02-15 16:54:18.000000000 +0100
e7a6f3
+++ net-tools-2.0/lib/interface.c	2016-03-30 09:58:18.247891588 +0200
e7a6f3
@@ -93,6 +93,7 @@ int if_list_all = 0;	/* do we have reque
e7a6f3
 static struct interface *int_list, *int_last;
e7a6f3
 
e7a6f3
 static int if_readlist_proc(const char *);
e7a6f3
+static int if_readlist_rep(const char *, struct interface *);
e7a6f3
 
e7a6f3
 static struct interface *if_cache_add(const char *name)
e7a6f3
 {
e7a6f3
@@ -138,11 +139,14 @@ struct interface *lookup_interface(const
e7a6f3
 int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
e7a6f3
 {
e7a6f3
     struct interface *ife;
e7a6f3
+    int err;
e7a6f3
 
e7a6f3
     if (!if_list_all && (if_readlist() < 0))
e7a6f3
 	return -1;
e7a6f3
     for (ife = int_list; ife; ife = ife->next) {
e7a6f3
-	int err = doit(ife, cookie);
e7a6f3
+	if_readlist_rep(ife->name, ife);
e7a6f3
+	err = doit(ife, cookie);
e7a6f3
+
e7a6f3
 	if (err)
e7a6f3
 	    return err;
e7a6f3
     }
e7a6f3
@@ -210,16 +214,24 @@ out:
e7a6f3
     return err;
e7a6f3
 }
e7a6f3
 
e7a6f3
-static const char *get_name(char *name, const char *p)
e7a6f3
+static const char *get_name(char **namep, const char *p)
e7a6f3
 {
e7a6f3
+    int count = 0;
e7a6f3
     while (isspace(*p))
e7a6f3
 	p++;
e7a6f3
+    char *name = *namep = p;
e7a6f3
     while (*p) {
e7a6f3
 	if (isspace(*p))
e7a6f3
 	    break;
e7a6f3
 	if (*p == ':') {	/* could be an alias */
e7a6f3
 		const char *dot = p++;
e7a6f3
- 		while (*p && isdigit(*p)) p++;
e7a6f3
+		count++;
e7a6f3
+		while (*p && isdigit(*p)) {
e7a6f3
+		    p++;
e7a6f3
+		    count++;
e7a6f3
+		    if (count == (IFNAMSIZ-1))
e7a6f3
+			break;
e7a6f3
+		}
e7a6f3
 		if (*p == ':') {
e7a6f3
 			/* Yes it is, backup and copy it. */
e7a6f3
 			p = dot;
e7a6f3
@@ -235,6 +247,9 @@ static const char *get_name(char *name,
e7a6f3
 	    break;
e7a6f3
 	}
e7a6f3
 	*name++ = *p++;
e7a6f3
+	count++;
e7a6f3
+	if (count == (IFNAMSIZ-1))
e7a6f3
+    	      break;
e7a6f3
     }
e7a6f3
     *name++ = '\0';
e7a6f3
     return p;
e7a6f3
@@ -316,9 +331,10 @@ static int get_dev_fields(const char *bp
e7a6f3
 static int if_readlist_proc(const char *target)
e7a6f3
 {
e7a6f3
     FILE *fh;
e7a6f3
-    char buf[512];
e7a6f3
     struct interface *ife;
e7a6f3
     int err;
e7a6f3
+    char *line = NULL;
e7a6f3
+    size_t linelen = 0;  
e7a6f3
 
e7a6f3
     fh = fopen(_PATH_PROCNET_DEV, "r");
e7a6f3
     if (!fh) {
e7a6f3
@@ -326,10 +342,11 @@ static int if_readlist_proc(const char *
e7a6f3
 			_PATH_PROCNET_DEV, strerror(errno));
e7a6f3
 		return -2;
e7a6f3
 	}
e7a6f3
-    if (fgets(buf, sizeof buf, fh))
e7a6f3
-		/* eat line */;
e7a6f3
-    if (fgets(buf, sizeof buf, fh))
e7a6f3
-		/* eat line */;
e7a6f3
+    if (getline(&line, &linelen, fh) == -1 /* eat line */
e7a6f3
+	|| getline(&line, &linelen, fh) == -1) { /* eat line */
e7a6f3
+		err = -1;
e7a6f3
+		goto out;
e7a6f3
+	}
e7a6f3
 
e7a6f3
 #if 0				/* pretty, but can't cope with missing fields */
e7a6f3
     fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
e7a6f3
@@ -354,14 +371,14 @@ static int if_readlist_proc(const char *
e7a6f3
     if (!fmt)
e7a6f3
 	return -1;
e7a6f3
 #else
e7a6f3
-    procnetdev_vsn = procnetdev_version(buf);
e7a6f3
+    procnetdev_vsn = procnetdev_version(line);
e7a6f3
 #endif
e7a6f3
 
e7a6f3
     err = 0;
e7a6f3
-    while (fgets(buf, sizeof buf, fh)) {
e7a6f3
+    while (getline(&line, &linelen, fh) != -1) {
e7a6f3
 	const char *s;
e7a6f3
-	char name[IFNAMSIZ];
e7a6f3
-	s = get_name(name, buf);
e7a6f3
+	char *name;
e7a6f3
+	s = get_name(&name, line);    
e7a6f3
 	ife = if_cache_add(name);
e7a6f3
 	get_dev_fields(s, ife);
e7a6f3
 	ife->statistics_valid = 1;
e7a6f3
@@ -376,6 +393,51 @@ static int if_readlist_proc(const char *
e7a6f3
 #if 0
e7a6f3
     free(fmt);
e7a6f3
 #endif
e7a6f3
+  out:
e7a6f3
+    free(line);
e7a6f3
+    fclose(fh);
e7a6f3
+    return err;
e7a6f3
+}
e7a6f3
+
e7a6f3
+static int if_readlist_rep(const char *target, struct interface *ife)
e7a6f3
+{
e7a6f3
+    FILE *fh;
e7a6f3
+    int err;
e7a6f3
+    char *line = NULL;
e7a6f3
+    size_t linelen = 0;
e7a6f3
+
e7a6f3
+    fh = fopen(_PATH_PROCNET_DEV, "r");
e7a6f3
+    if (!fh) {
e7a6f3
+		fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
e7a6f3
+			_PATH_PROCNET_DEV, strerror(errno)); 
e7a6f3
+		return if_readconf();
e7a6f3
+	}
e7a6f3
+    if (getline(&line, &linelen, fh) == -1 /* eat line */
e7a6f3
+	|| getline(&line, &linelen, fh) == -1) { /* eat line */
e7a6f3
+		err = -1;
e7a6f3
+		goto out;
e7a6f3
+	}
e7a6f3
+
e7a6f3
+    procnetdev_vsn = procnetdev_version(line);
e7a6f3
+
e7a6f3
+    err = 0;
e7a6f3
+    while (getline(&line, &linelen, fh) != -1) {
e7a6f3
+	char *s, *name;
e7a6f3
+	s = get_name(&name, line);    
e7a6f3
+	get_dev_fields(s, ife);
e7a6f3
+	if (target && !strcmp(target,name))
e7a6f3
+	{
e7a6f3
+		ife->statistics_valid = 1;
e7a6f3
+		break;
e7a6f3
+	}
e7a6f3
+    }
e7a6f3
+    if (ferror(fh)) {
e7a6f3
+	perror(_PATH_PROCNET_DEV);
e7a6f3
+	err = -1;
e7a6f3
+    }
e7a6f3
+
e7a6f3
+  out:
e7a6f3
+    free(line);
e7a6f3
     fclose(fh);
e7a6f3
     return err;
e7a6f3
 }
e7a6f3
diff -up net-tools-2.0/man/en_US/netstat.8.cycle net-tools-2.0/man/en_US/netstat.8
e7a6f3
--- net-tools-2.0/man/en_US/netstat.8.cycle	2016-02-15 16:54:18.000000000 +0100
e7a6f3
+++ net-tools-2.0/man/en_US/netstat.8	2016-03-30 09:58:18.241891637 +0200
e7a6f3
@@ -36,6 +36,7 @@ netstat \- Print network connections, ro
e7a6f3
 .RB [ \-\-verbose | \-v ]
e7a6f3
 .RB [ \-\-continuous | \-c]
e7a6f3
 .RB [ \-\-wide | \-W ]
e7a6f3
+.RB [delay]
e7a6f3
 .P
e7a6f3
 .B netstat 
e7a6f3
 .RB { \-\-route | \-r }
e7a6f3
@@ -45,22 +46,25 @@ netstat \- Print network connections, ro
e7a6f3
 .RB [ \-\-numeric | \-n ]
e7a6f3
 .RB [ \-\-numeric\-hosts "] [" \-\-numeric\-ports "] [" \-\-numeric\-users ]
e7a6f3
 .RB [ \-\-continuous | \-c ]
e7a6f3
+.RB [delay]
e7a6f3
 .P
e7a6f3
 .B netstat
e7a6f3
-.RB { \-\-interfaces | \-i }
e7a6f3
+.RB { \-\-interfaces | \-I | \-i }
e7a6f3
 .RB [ \-\-all | \-a ]
e7a6f3
-.RB [ \-\-extend | \-e  [ \-\-extend | \-e] ]
e7a6f3
+.RB [ \-\-extend | \-e  ]
e7a6f3
 .RB [ \-\-verbose | \-v ]
e7a6f3
 .RB [ \-\-program | \-p ]
e7a6f3
 .RB [ \-\-numeric | \-n ]
e7a6f3
 .RB [ \-\-numeric-hosts "] [" \-\-numeric-ports "] [" \-\-numeric-users ]
e7a6f3
 .RB [ \-\-continuous | \-c ]
e7a6f3
+.RB [delay]
e7a6f3
 .P
e7a6f3
 .B netstat
e7a6f3
 .RB { \-\-groups | \-g }
e7a6f3
 .RB [ \-\-numeric | \-n ]
e7a6f3
 .RB [ \-\-numeric\-hosts "] [" \-\-numeric\-ports "] [" \-\-numeric\-users ]
e7a6f3
 .RB [ \-\-continuous | \-c ]
e7a6f3
+.RB [delay]
e7a6f3
 .P
e7a6f3
 .B netstat
e7a6f3
 .RB { \-\-masquerade | \-M }
e7a6f3
@@ -68,6 +72,7 @@ netstat \- Print network connections, ro
e7a6f3
 .RB [ \-\-numeric | \-n ]
e7a6f3
 .RB [ \-\-numeric\-hosts "] [" \-\-numeric\-ports "] [" \-\-numeric\-users ]
e7a6f3
 .RB [ \-\-continuous | \-c ]
e7a6f3
+.RB [delay]
e7a6f3
 .P
e7a6f3
 .B netstat
e7a6f3
 .RB { \-\-statistics | -s }
e7a6f3
@@ -76,6 +81,7 @@ netstat \- Print network connections, ro
e7a6f3
 .RB [ \-\-udplite | \-U ]
e7a6f3
 .RB [ \-\-sctp | \-S ]
e7a6f3
 .RB [ \-\-raw | \-w ]
e7a6f3
+.RB [delay]
e7a6f3
 .P
e7a6f3
 .B netstat 
e7a6f3
 .RB { \-\-version | \-V }
e7a6f3
@@ -128,8 +134,8 @@ and
e7a6f3
 produce the same output.
e7a6f3
 .SS "\-\-groups, \-g"
e7a6f3
 Display multicast group membership information for IPv4 and IPv6.
e7a6f3
-.SS "\-\-interfaces, \-i"
e7a6f3
-Display a table of all network interfaces.
e7a6f3
+.SS "\-\-interfaces=\fIiface \fR, \fB\-I=\fIiface \fR, \fB\-i"
e7a6f3
+Display a table of all network interfaces, or the specified \fIiface\fR.
e7a6f3
 .SS "\-\-masquerade, \-M"
e7a6f3
 Display a list of masqueraded connections.
e7a6f3
 .SS "\-\-statistics, \-s"
e7a6f3
@@ -201,13 +207,18 @@ Show the PID and name of the program to
e7a6f3
 .SS "\-l, \-\-listening"
e7a6f3
 Show only listening sockets.  (These are omitted by default.)
e7a6f3
 .SS "\-a, \-\-all"
e7a6f3
-Show both listening and non-listening sockets.  With the
e7a6f3
+Show both listening and non-listening (for TCP this means established
e7a6f3
+connections) sockets.  With the
e7a6f3
 .B \-\-interfaces
e7a6f3
 option, show interfaces that are not up
e7a6f3
 .SS "\-F"
e7a6f3
 Print routing information from the FIB.  (This is the default.)
e7a6f3
 .SS "\-C"
e7a6f3
 Print routing information from the route cache.
e7a6f3
+.SS delay
e7a6f3
+Netstat will cycle printing through statistics every 
e7a6f3
+.B delay 
e7a6f3
+seconds.
e7a6f3
 .P
e7a6f3
 .SH OUTPUT
e7a6f3
 .P
e7a6f3
diff -up net-tools-2.0/netstat.c.cycle net-tools-2.0/netstat.c
e7a6f3
--- net-tools-2.0/netstat.c.cycle	2016-02-15 16:54:18.000000000 +0100
e7a6f3
+++ net-tools-2.0/netstat.c	2016-03-30 10:04:07.617171984 +0200
e7a6f3
@@ -115,8 +115,8 @@
e7a6f3
 #endif
e7a6f3
 
e7a6f3
 /* prototypes for statistics.c */
e7a6f3
-void parsesnmp(int, int, int, int);
e7a6f3
-void parsesnmp6(int, int, int);
e7a6f3
+int parsesnmp(int, int, int, int);
e7a6f3
+int parsesnmp6(int, int, int);
e7a6f3
 
e7a6f3
 typedef enum {
e7a6f3
     SS_FREE = 0,		/* not allocated                */
e7a6f3
@@ -142,6 +142,7 @@ static char *Release = RELEASE, *Signatu
e7a6f3
 #define E_IOCTL -3
e7a6f3
 
e7a6f3
 int flag_int = 0;
e7a6f3
+char *flag_int_name = NULL;
e7a6f3
 int flag_rou = 0;
e7a6f3
 int flag_mas = 0;
e7a6f3
 int flag_sta = 0;
e7a6f3
@@ -340,10 +341,10 @@ static void prg_cache_clear(void)
e7a6f3
     prg_cache_loaded = 0;
e7a6f3
 }
e7a6f3
 
e7a6f3
-static void wait_continous(void)
e7a6f3
+static void wait_continous(int reptimer)
e7a6f3
 {
e7a6f3
     fflush(stdout);
e7a6f3
-    sleep(1);
e7a6f3
+    sleep(reptimer);
e7a6f3
 }
e7a6f3
 
e7a6f3
 static int extract_type_1_socket_inode(const char lname[], unsigned long * inode_p) {
e7a6f3
@@ -501,6 +502,121 @@ static void prg_cache_load(void)
e7a6f3
 			 " will not be shown, you would have to be root to see it all.)\n"));
e7a6f3
 }
e7a6f3
 
e7a6f3
+#define TCP_HASH_SIZE 1009
e7a6f3
+
e7a6f3
+static struct tcp_node {
e7a6f3
+  struct tcp_node *next;
e7a6f3
+  char            *socket_pair;
e7a6f3
+} *tcp_node_hash[TCP_HASH_SIZE];
e7a6f3
+
e7a6f3
+static unsigned int tcp_node_compute_string_hash(const char *p)
e7a6f3
+{
e7a6f3
+  unsigned int h = *p;
e7a6f3
+
e7a6f3
+  if (h)
e7a6f3
+    for (p += 1; *p != '\0'; p++)
e7a6f3
+      h = (h << 5) - h + *p;
e7a6f3
+
e7a6f3
+  return h;
e7a6f3
+}
e7a6f3
+
e7a6f3
+#define TCP_NODE_HASH_STRING(x) \
e7a6f3
+  (tcp_node_compute_string_hash(x) % TCP_HASH_SIZE)
e7a6f3
+
e7a6f3
+static void tcp_node_hash_clear(void)
e7a6f3
+{
e7a6f3
+  int i;
e7a6f3
+  struct tcp_node *next_node;
e7a6f3
+  struct tcp_node *tmp_node;
e7a6f3
+  for (i=0; i < TCP_HASH_SIZE; i++) {
e7a6f3
+    if (tcp_node_hash[i]) {
e7a6f3
+      /* free the children of this hash bucket */
e7a6f3
+      next_node = tcp_node_hash[i]->next;
e7a6f3
+      while (next_node) {
e7a6f3
+	tmp_node = next_node;
e7a6f3
+	next_node = next_node->next;
e7a6f3
+	free(tmp_node->socket_pair);
e7a6f3
+	free(tmp_node);
e7a6f3
+      }
e7a6f3
+
e7a6f3
+      /* free the bucket itself */
e7a6f3
+      free(tcp_node_hash[i]->socket_pair);
e7a6f3
+      free(tcp_node_hash[i]);
e7a6f3
+      tcp_node_hash[i] = NULL;
e7a6f3
+    }
e7a6f3
+  }
e7a6f3
+}
e7a6f3
+
e7a6f3
+/* This function takes a socket pair string.  If it already exists in
e7a6f3
+   the hash it returns -1, otherwise it returns 0. */
e7a6f3
+
e7a6f3
+static int tcp_node_hash_check_and_append(const char *local_addr,
e7a6f3
+					  int local_port,
e7a6f3
+					  const char *rem_addr,
e7a6f3
+					  int rem_port)
e7a6f3
+{
e7a6f3
+  unsigned int hash_val;
e7a6f3
+  struct tcp_node *tmp_node;
e7a6f3
+  int   tmp_string_len;
e7a6f3
+  char *tmp_string;;
e7a6f3
+
e7a6f3
+  /* Size of the string is the size of the two lengths of the address
e7a6f3
+     strings plus enough sizes for the colons and the ports. */
e7a6f3
+  tmp_string_len = strlen(local_addr) + strlen(rem_addr) + 32;
e7a6f3
+  tmp_string = malloc(tmp_string_len);
e7a6f3
+  if (!tmp_string)
e7a6f3
+    return 0;
e7a6f3
+
e7a6f3
+  if (snprintf(tmp_string, tmp_string_len - 1, "%s:%d:%s:%d",
e7a6f3
+	       local_addr, local_port, rem_addr, rem_port) < 0) {
e7a6f3
+    free(tmp_string);
e7a6f3
+    return 0;
e7a6f3
+  }
e7a6f3
+
e7a6f3
+  hash_val = TCP_NODE_HASH_STRING(tmp_string);
e7a6f3
+
e7a6f3
+  /* See if we have to allocate this node */
e7a6f3
+  if (!tcp_node_hash[hash_val]) {
e7a6f3
+    tcp_node_hash[hash_val] = malloc(sizeof(struct tcp_node));
e7a6f3
+    if (!tcp_node_hash[hash_val]) {
e7a6f3
+      free(tmp_string);
e7a6f3
+      return 0;
e7a6f3
+    }
e7a6f3
+
e7a6f3
+    memset(tcp_node_hash[hash_val], 0, sizeof(struct tcp_node));
e7a6f3
+
e7a6f3
+    /* Stuff this new value into the hash bucket and return early */
e7a6f3
+    tcp_node_hash[hash_val]->socket_pair = tmp_string;
e7a6f3
+    return 0;
e7a6f3
+  }
e7a6f3
+
e7a6f3
+  /* Try to find the value in the hash bucket. */
e7a6f3
+  tmp_node = tcp_node_hash[hash_val];
e7a6f3
+  while (tmp_node) {
e7a6f3
+    if (!strcmp(tmp_node->socket_pair, tmp_string)) {
e7a6f3
+      free(tmp_string);
e7a6f3
+      return -1;
e7a6f3
+    }
e7a6f3
+    tmp_node = tmp_node->next;
e7a6f3
+  }
e7a6f3
+
e7a6f3
+  /* If we got this far it means that it isn't in the hash bucket.
e7a6f3
+     Add it to the front since it's faster that way. */
e7a6f3
+  tmp_node = tcp_node_hash[hash_val];
e7a6f3
+
e7a6f3
+  tcp_node_hash[hash_val] = malloc(sizeof(struct tcp_node));
e7a6f3
+  if (!tcp_node_hash[hash_val]) {
e7a6f3
+    free(tmp_string);
e7a6f3
+    tcp_node_hash[hash_val] = tmp_node;
e7a6f3
+    return 0;
e7a6f3
+  }
e7a6f3
+
e7a6f3
+  tcp_node_hash[hash_val]->socket_pair = tmp_string;
e7a6f3
+  tcp_node_hash[hash_val]->next = tmp_node;
e7a6f3
+
e7a6f3
+  return 0;
e7a6f3
+}
e7a6f3
+
e7a6f3
 #if HAVE_AFNETROM
e7a6f3
 static const char *netrom_state[] =
e7a6f3
 {
e7a6f3
@@ -1109,6 +1225,12 @@ static void tcp_do_one(int lnr, const ch
e7a6f3
 	return;
e7a6f3
     }
e7a6f3
 
e7a6f3
+    /* make sure that we haven't seen this socket pair before */
e7a6f3
+    if (tcp_node_hash_check_and_append(local_addr, local_port, rem_addr, rem_port) < 0) {
e7a6f3
+    	/*  fprintf(stderr, _("warning, got duplicate tcp line.\n")); */
e7a6f3
+    	return;
e7a6f3
+    }
e7a6f3
+
e7a6f3
 	addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localsas, local_port, "tcp");
e7a6f3
 	addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remsas, rem_port, "tcp");
e7a6f3
 
e7a6f3
@@ -1877,6 +1999,9 @@ static int rfcomm_info(void)
e7a6f3
 
e7a6f3
 static int iface_info(void)
e7a6f3
 {
e7a6f3
+    static int count=0;
e7a6f3
+    struct interface *ife = NULL;
e7a6f3
+
e7a6f3
     if (skfd < 0) {
e7a6f3
 	if ((skfd = sockets_open(0)) < 0) {
e7a6f3
 	    perror("socket");
e7a6f3
@@ -1886,20 +2011,25 @@ static int iface_info(void)
e7a6f3
     }
e7a6f3
     if (flag_exp < 2) {
e7a6f3
 	ife_short = 1;
e7a6f3
-	printf(_("Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
e7a6f3
+	if(!(count % 8))
e7a6f3
+	    printf(_("Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
e7a6f3
     }
e7a6f3
 
e7a6f3
-    if (for_all_interfaces(do_if_print, &flag_all) < 0) {
e7a6f3
+    if (flag_int_name) {
e7a6f3
+        ife = lookup_interface(flag_int_name);
e7a6f3
+        do_if_print(ife, &flag_all);
e7a6f3
+    }
e7a6f3
+    else if (for_all_interfaces(do_if_print, &flag_all) < 0) {
e7a6f3
 	perror(_("missing interface information"));
e7a6f3
 	exit(1);
e7a6f3
     }
e7a6f3
-    if (flag_cnt)
e7a6f3
+    if (!flag_cnt) {
e7a6f3
 	if_cache_free();
e7a6f3
-    else {
e7a6f3
 	close(skfd);
e7a6f3
 	skfd = -1;
e7a6f3
     }
e7a6f3
 
e7a6f3
+    count++;
e7a6f3
     return 0;
e7a6f3
 }
e7a6f3
 
e7a6f3
@@ -1915,9 +2045,10 @@ static void usage(int rc)
e7a6f3
 {
e7a6f3
     fprintf(stderr, _("usage: netstat [-vWeenNcCF] [<Af>] -r         netstat {-V|--version|-h|--help}\n"));
e7a6f3
     fprintf(stderr, _("       netstat [-vWnNcaeol] [<Socket> ...]\n"));
e7a6f3
-    fprintf(stderr, _("       netstat { [-vWeenNac] -i | [-cnNe] -M | -s [-6tuw] }\n\n"));
e7a6f3
+    fprintf(stderr, _("       netstat { [-vWeenNac] -I[<Iface>] | [-veenNac] -i | [-cnNe] -M | -s [-6tuw] } [delay]\n\n"));
e7a6f3
 
e7a6f3
     fprintf(stderr, _("        -r, --route              display routing table\n"));
e7a6f3
+    fprintf(stderr, _("        -I, --interfaces=<Iface> display interface table for <Iface>\n"));
e7a6f3
     fprintf(stderr, _("        -i, --interfaces         display interface table\n"));
e7a6f3
     fprintf(stderr, _("        -g, --groups             display multicast group memberships\n"));
e7a6f3
     fprintf(stderr, _("        -s, --statistics         display networking statistics (like SNMP)\n"));
e7a6f3
@@ -1957,11 +2088,12 @@ int main
e7a6f3
  (int argc, char *argv[]) {
e7a6f3
     int i;
e7a6f3
     int lop;
e7a6f3
+    int reptimer = 1;
e7a6f3
     static struct option longopts[] =
e7a6f3
     {
e7a6f3
 	AFTRANS_OPTS,
e7a6f3
 	{"version", 0, 0, 'V'},
e7a6f3
-	{"interfaces", 0, 0, 'i'},
e7a6f3
+	{"interfaces", 2, 0, 'I'},
e7a6f3
 	{"help", 0, 0, 'h'},
e7a6f3
 	{"route", 0, 0, 'r'},
e7a6f3
 #if HAVE_FW_MASQUERADE
e7a6f3
@@ -2005,7 +2137,7 @@ int main
e7a6f3
     getroute_init();		/* Set up AF routing support */
e7a6f3
 
e7a6f3
     afname[0] = '\0';
e7a6f3
-    while ((i = getopt_long(argc, argv, "A:CFMacdeghilnNoprsStuUvVWw2fx64?Z", longopts, &lop)) != EOF)
e7a6f3
+    while ((i = getopt_long(argc, argv, "A:CFMacdeghiI::lnNoprsStuUvVWw2fx64?Z", longopts, &lop)) != EOF)
e7a6f3
 	switch (i) {
e7a6f3
 	case -1:
e7a6f3
 	    break;
e7a6f3
@@ -2046,6 +2178,13 @@ int main
e7a6f3
 	case 'p':
e7a6f3
 	    flag_prg++;
e7a6f3
 	    break;
e7a6f3
+	case 'I':
e7a6f3
+	    if (optarg && strcmp(optarg, "(null)"))
e7a6f3
+		if (optarg[0] == '=') optarg++;
e7a6f3
+	    if (optarg && strcmp(optarg, "(null)"))
e7a6f3
+		flag_int_name = strdup(optarg);
e7a6f3
+	    flag_int++;
e7a6f3
+	    break;
e7a6f3
 	case 'i':
e7a6f3
 	    flag_int++;
e7a6f3
 	    break;
e7a6f3
@@ -2140,6 +2279,12 @@ int main
e7a6f3
 	    flag_sta++;
e7a6f3
 	}
e7a6f3
 
e7a6f3
+    if(argc == optind + 1) {
e7a6f3
+    	if((reptimer = atoi(argv[optind])) <= 0)
e7a6f3
+    		usage(E_USAGE);
e7a6f3
+        flag_cnt++;
e7a6f3
+    }
e7a6f3
+
e7a6f3
     if (flag_int + flag_rou + flag_mas + flag_sta > 1)
e7a6f3
 	usage(E_OPTERR);
e7a6f3
 
e7a6f3
@@ -2169,7 +2314,7 @@ int main
e7a6f3
 			     flag_not & FLAG_NUM_PORT, flag_exp);
e7a6f3
 	    if (i || !flag_cnt)
e7a6f3
 		break;
e7a6f3
-	    wait_continous();
e7a6f3
+	    wait_continous(reptimer);
e7a6f3
 	}
e7a6f3
 #else
e7a6f3
 	ENOSUPP("netstat", "FW_MASQUERADE");
e7a6f3
@@ -2182,15 +2327,16 @@ int main
e7a6f3
         if (!afname[0])
e7a6f3
             safe_strncpy(afname, DFLT_AF, sizeof(afname));
e7a6f3
 
e7a6f3
+        for (;;) {
e7a6f3
         if (!strcmp(afname, "inet")) {
e7a6f3
 #if HAVE_AFINET
e7a6f3
-            parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp);
e7a6f3
+            i = parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp);
e7a6f3
 #else
e7a6f3
             ENOSUPP("netstat", "AF INET");
e7a6f3
 #endif
e7a6f3
         } else if(!strcmp(afname, "inet6")) {
e7a6f3
 #if HAVE_AFINET6
e7a6f3
-            parsesnmp6(flag_raw, flag_tcp, flag_udp);
e7a6f3
+            i = parsesnmp6(flag_raw, flag_tcp, flag_udp);
e7a6f3
 #else
e7a6f3
             ENOSUPP("netstat", "AF INET6");
e7a6f3
 #endif
e7a6f3
@@ -2198,7 +2344,11 @@ int main
e7a6f3
           printf(_("netstat: No statistics support for specified address family: %s\n"), afname);
e7a6f3
           exit(1);
e7a6f3
         }
e7a6f3
-        exit(0);
e7a6f3
+	if(i || !flag_cnt)
e7a6f3
+	  break;
e7a6f3
+	sleep(reptimer);
e7a6f3
+        }
e7a6f3
+        return (i);
e7a6f3
     }
e7a6f3
 
e7a6f3
     if (flag_rou) {
e7a6f3
@@ -2220,7 +2370,7 @@ int main
e7a6f3
 	    i = route_info(afname, options);
e7a6f3
 	    if (i || !flag_cnt)
e7a6f3
 		break;
e7a6f3
-            wait_continous();
e7a6f3
+            wait_continous(reptimer);
e7a6f3
 	}
e7a6f3
 	return (i);
e7a6f3
     }
e7a6f3
@@ -2229,7 +2379,7 @@ int main
e7a6f3
 	    i = iface_info();
e7a6f3
 	    if (!flag_cnt || i)
e7a6f3
 		break;
e7a6f3
-            wait_continous();
e7a6f3
+            wait_continous(reptimer);
e7a6f3
 	}
e7a6f3
 	return (i);
e7a6f3
     }
e7a6f3
@@ -2416,8 +2566,9 @@ int main
e7a6f3
 
e7a6f3
 	if (!flag_cnt || i)
e7a6f3
 	    break;
e7a6f3
-        wait_continous();
e7a6f3
+        wait_continous(reptimer);
e7a6f3
 	prg_cache_clear();
e7a6f3
+	tcp_node_hash_clear();
e7a6f3
     }
e7a6f3
     return (i);
e7a6f3
 }
e7a6f3
diff -up net-tools-2.0/statistics.c.cycle net-tools-2.0/statistics.c
e7a6f3
--- net-tools-2.0/statistics.c.cycle	2016-02-15 16:54:18.000000000 +0100
e7a6f3
+++ net-tools-2.0/statistics.c	2016-03-30 09:58:18.238891661 +0200
e7a6f3
@@ -527,7 +527,7 @@ static void process_fd2(FILE *f, const c
e7a6f3
     }
e7a6f3
 }
e7a6f3
 
e7a6f3
-void parsesnmp(int flag_raw, int flag_tcp, int flag_udp, int flag_sctp)
e7a6f3
+int parsesnmp(int flag_raw, int flag_tcp, int flag_udp, int flag_sctp)
e7a6f3
 {
e7a6f3
     FILE *f;
e7a6f3
 
e7a6f3
@@ -536,14 +536,17 @@ void parsesnmp(int flag_raw, int flag_tc
e7a6f3
     f = proc_fopen("/proc/net/snmp");
e7a6f3
     if (!f) {
e7a6f3
 	perror(_("cannot open /proc/net/snmp"));
e7a6f3
-	return;
e7a6f3
+	return(1);
e7a6f3
     }
e7a6f3
 
e7a6f3
     if (process_fd(f, 1, NULL) < 0)
e7a6f3
       fprintf(stderr, _("Problem while parsing /proc/net/snmp\n"));
e7a6f3
 
e7a6f3
-    if (ferror(f))
e7a6f3
+    if (ferror(f)) {
e7a6f3
 	perror("/proc/net/snmp");
e7a6f3
+	fclose(f);
e7a6f3
+	return(1);
e7a6f3
+    }
e7a6f3
 
e7a6f3
     fclose(f);
e7a6f3
 
e7a6f3
@@ -553,8 +556,11 @@ void parsesnmp(int flag_raw, int flag_tc
e7a6f3
     	if (process_fd(f, 1, NULL) <0)
e7a6f3
           fprintf(stderr, _("Problem while parsing /proc/net/netstat\n"));
e7a6f3
 
e7a6f3
-        if (ferror(f))
e7a6f3
-	    perror("/proc/net/netstat");
e7a6f3
+        if (ferror(f)) {
e7a6f3
+	  perror("/proc/net/netstat");
e7a6f3
+	  fclose(f);
e7a6f3
+	  return(1);
e7a6f3
+        }
e7a6f3
 
e7a6f3
         fclose(f);
e7a6f3
     }
e7a6f3
@@ -567,9 +573,10 @@ void parsesnmp(int flag_raw, int flag_tc
e7a6f3
 	    fclose(f);
e7a6f3
 	}
e7a6f3
     }
e7a6f3
+    return(0);
e7a6f3
 }
e7a6f3
 
e7a6f3
-void parsesnmp6(int flag_raw, int flag_tcp, int flag_udp)
e7a6f3
+int parsesnmp6(int flag_raw, int flag_tcp, int flag_udp)
e7a6f3
 {
e7a6f3
     FILE *f;
e7a6f3
 
e7a6f3
@@ -578,7 +585,7 @@ void parsesnmp6(int flag_raw, int flag_t
e7a6f3
     f = fopen("/proc/net/snmp6", "r");
e7a6f3
     if (!f) {
e7a6f3
         perror(_("cannot open /proc/net/snmp6"));
e7a6f3
-        return;
e7a6f3
+        return(1);
e7a6f3
     }
e7a6f3
     process6_fd(f);
e7a6f3
     if (ferror(f))
e7a6f3
@@ -588,11 +595,14 @@ void parsesnmp6(int flag_raw, int flag_t
e7a6f3
     f = fopen("/proc/net/snmp", "r");
e7a6f3
     if (!f) {
e7a6f3
         perror(_("cannot open /proc/net/snmp"));
e7a6f3
-        return;
e7a6f3
+        return(1);
e7a6f3
     }
e7a6f3
     process_fd(f, 0, "Tcp");
e7a6f3
-    if (ferror(f))
e7a6f3
+    if (ferror(f)) {
e7a6f3
         perror("/proc/net/snmp");
e7a6f3
+        return(1);
e7a6f3
+    }
e7a6f3
 
e7a6f3
     fclose(f);
e7a6f3
+    return(0);
e7a6f3
 }