Bug#697367: tcpstat hangs in capture mode when no packets arrive

2013-01-08 Thread Rafael Cunha de Almeida
Thank you for your patch! I haven't had much time to look at it yet, but it
seems good from my first look. I'll take a better look at it later.

On Fri, Jan 04, 2013 at 02:39:29PM +0100, lemonsqueeze wrote:
 Here is a patch against 1.5-7 that fixes it. Contacted upstream about
 it, it is unclear if new versions of the package will be released, so
 posting it here.

I had the same issue when contacting upstream regarding my tcpprof patch. Are
you able to quote us the relevant parts of your conversation with upstream? I
ask that only for documentation purposes.

I need to further investigate what is the best practice when fixing bugs of a
dead upstream project. The problem is that each patch I add to the package, we
deviate from upstream further and further. It could become a problem for future
maintainers if upstream ever releases a new version.

 - use setitimer() instead of ualarm(): not limited to 1s (linux)

According to setitimer manpage, setitimer is obsolete and timer_settime should
be used instead. Debian's libc seems to support timer_settime. Is there a reason
not to use timer_settime instead of setitimer?

Cheers,
Rafael


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#697367: tcpstat hangs in capture mode when no packets arrive

2013-01-04 Thread lemonsqueeze
Package: tcpstat
Version: 1.5-7
Severity: normal
Tags: patch

When running tcpstat in capture mode, output hangs while no packets
arrive. For example

  # tcpstat -i eth0 1

should print output every second, but instead hangs while there's no
network traffic. Missing output comes up all at once once a packet
arrives. (actually even when there is traffic the output timing is off,
but less obvious)

This bug is known and documented in the man page.
Packages based on upstream v1.5 code are affected.

Here is a patch against 1.5-7 that fixes it. Contacted upstream about
it, it is unclear if new versions of the package will be released, so
posting it here.

- main loop, fix untimely display in live capture mode:
  all: decoupled data logic and display logic,
  process.c: changed alarm handler to catch interval timeouts.
 capture_seconds logic now on top of interval
 logic.
- use setitimer() instead of ualarm(): not limited to 1s (linux)

Did a bit of testing, couldn't find anything it breaks from what i can
tell (under linux at least):

tcpstat works both in capture and file mode,
-s now works in capture mode,
intervals less and greater than 1s work in capture mode.
tcpprof and packetdump look fine also.

Cheers
--
Matthieu

diff -Nru tcpstat-1.5/configure.in tcpstat-1.5_fix/configure.in
--- tcpstat-1.5/configure.in	2013-01-04 14:12:58.0 +0100
+++ tcpstat-1.5_fix/configure.in	2013-01-04 14:01:07.0 +0100
@@ -102,7 +102,7 @@
 dnl 
 dnl Checks for library functions
 dnl 
-AC_CHECK_FUNCS(strtol strtoul ualarm perror inet_ntop)
+AC_CHECK_FUNCS(strtol strtoul setitimer perror inet_ntop)
 AC_CHECK_FUNCS(snprintf, , [
 echo WARNING:  You don't seem to have snprintf() (Solaris 2.5.x?)
 echo   There may be a slight security problem without it.
diff -Nru tcpstat-1.5/doc/tcpstat.1 tcpstat-1.5_fix/doc/tcpstat.1
--- tcpstat-1.5/doc/tcpstat.1	2013-01-04 14:12:58.0 +0100
+++ tcpstat-1.5_fix/doc/tcpstat.1	2013-01-04 14:01:01.0 +0100
@@ -345,11 +345,6 @@
 .Pp
 Please send all bug reports to this address.
 .Sh BUGS
-Due to a bug in libpcap, tcpstat will hang indefinitely under Linux 
-when no packets arrive.  This is because the timeout in pcap_open_live()
-is ignored under Linux when the interface is idle, which causes pcap_dispatch()
-to never return.
-.Pp
 Not tested with link types other than Ethernet, PPP, and None types.  
 .Pp
 There may be problems reading non-IPv4 packets across platforms when
diff -Nru tcpstat-1.5/include/config.h.in tcpstat-1.5_fix/include/config.h.in
--- tcpstat-1.5/include/config.h.in	2013-01-04 14:12:58.0 +0100
+++ tcpstat-1.5_fix/include/config.h.in	2013-01-04 14:01:07.0 +0100
@@ -72,8 +72,8 @@
 /* Define if you have sys/wait.h that is POSIX.1 compatible. */
 #undef HAVE_SYS_WAIT_H
 
-/* Define if you have the `ualarm' function. */
-#undef HAVE_UALARM
+/* Define if you have the `setitimer' function. */
+#undef HAVE_SETITIMER
 
 /* Define if you have the unistd.h header file. */
 #undef HAVE_UNISTD_H
diff -Nru tcpstat-1.5/include/tcpstat.h tcpstat-1.5_fix/include/tcpstat.h
--- tcpstat-1.5/include/tcpstat.h	2002-06-01 08:42:08.0 +0200
+++ tcpstat-1.5_fix/include/tcpstat.h	2013-01-04 14:01:01.0 +0100
@@ -234,8 +234,9 @@
 
 /* process.c protos */
 int  get_dump_data(char *fname, char *filter, int flags,
-Double capture_seconds, void (*hook)(packet_data *, void **),
-	void **args);
+		  Double interval, Double capture_seconds,
+		  void (*data_hook)(packet_data *, void **), void **args,
+		  void (*display_hook)(void **));
 
 /* print_packet.c protos */
 void print_packet(packet_data *p, int what_to_print);
diff -Nru tcpstat-1.5/lib/process.c tcpstat-1.5_fix/lib/process.c
--- tcpstat-1.5/lib/process.c	2002-06-01 08:42:09.0 +0200
+++ tcpstat-1.5_fix/lib/process.c	2013-01-04 14:01:07.0 +0100
@@ -30,16 +30,8 @@
 #include tcpstat.h
 #include snoop.h
 
-	/* Set alarm in 10 minute (600 seconds) steps
-	 * This is necessary, because ualarm() is usually limited:
-	 * FreeBSD, Solaris:	2^32/10^6 seconds (71m 35s)
-	 * Linux:	??
-	 */
-#define SECONDS_STEP	600.0
-
 packet_data	pdata;
 int		run;
-Double		seconds_left;
 
 struct	hook_and_sinker {
 	void 	(*hook)(packet_data *, void **);
@@ -48,10 +40,16 @@
 	bpf_u_int32	linktype;
 };
 
-void process_catch_alarm(int a) {
-	seconds_left -= SECONDS_STEP;
-	if (seconds_left = 0 || a == SIGINT) run = 0;
-	else my_alarm((seconds_left  SECONDS_STEP)? SECONDS_STEP : seconds_left);
+void sigint_handler(int a){
+run = 0;
+}
+
+static pcap_t	*pd = 0;
+static int	interval_timeout = 0;
+
+void interval_timeout_handler(int a) {
+	interval_timeout = 1;
+	pcap_breakloop(pd);
 }
 
 #define MAGIC_SIZE	2
@@ -311,14 +309,14 @@
  *   calls a user function pointing to the data
  */
 int get_pcap_data(char *fname, char *filter, int flags,
-	Double capture_seconds, void