Hi, MartМn.
The fix for an UDP timeout handling bug is in a patch below.
It was compiled with lzo1 and verified on Debian/testing.
Version of VTUN was incremented to 3.0.2.
In next mail I'll return to the discussion and answer questions.
--
Eugene Berdnikov
------------------------------------------------------------------------
diff -ru vtun-3.0.1/cfg_file.y vtun-3.0.2/cfg_file.y
--- vtun-3.0.1/cfg_file.y 2006-12-11 10:55:06.000000000 +0300
+++ vtun-3.0.2/cfg_file.y 2007-10-17 21:28:21.000000000 +0400
@@ -149,7 +149,7 @@
| K_BINDADDR '{' bindaddr_option '}'
| K_IFACE STRING {
- if(vtun.svr_addr == -1)
+ if(vtun.svr_addr != NULL)
vtun.svr_addr = strdup($2);
}
@@ -368,7 +368,7 @@
if( yylval.dnum.num1 ){
parse_host->flags |= VTUN_KEEP_ALIVE;
parse_host->ka_interval = yylval.dnum.num1;
- parse_host->ka_failure = yylval.dnum.num2;
+ parse_host->ka_maxfail = yylval.dnum.num2;
}
}
diff -ru vtun-3.0.1/ChangeLog vtun-3.0.2/ChangeLog
--- vtun-3.0.1/ChangeLog 2007-06-12 13:44:27.000000000 +0400
+++ vtun-3.0.2/ChangeLog 2007-10-18 20:23:00.000000000 +0400
@@ -1,3 +1,11 @@
+3.0.2:
+ Fixed Bug#339364: link timeout in UDP mode (Eugene Berdnikov)
+ Minor fixes in lfd_lzo.c to ensure correct type casting.
+ Minor fixes in cfg_file.y to ensure correct type casting.
+ Add description of "keepalive timeout:count;" syntax to man page
+ and vtund.conf sample.
+ Remove doubled if(send_a_file){...} block in linkfd.c.
+
3.0.1:
rfe1602625 - fix build for lzo2 (bc,db,ruzsi)
rfe780607 - new debian rc scripts (surgo)
diff -ru vtun-3.0.1/lfd_lzo.c vtun-3.0.2/lfd_lzo.c
--- vtun-3.0.1/lfd_lzo.c 2007-06-06 12:48:14.000000000 +0400
+++ vtun-3.0.2/lfd_lzo.c 2007-10-17 20:09:43.000000000 +0400
@@ -35,6 +35,7 @@
#ifdef HAVE_LZO
+#include "lzoutil.h"
#include "lzo1x.h"
#include "lzoutil.h"
@@ -54,7 +55,7 @@
int alloc_lzo(struct vtun_host *host)
{
int zlevel = host->zlevel ? host->zlevel : 1;
- int mem;
+ lzo_uint mem;
switch( zlevel ){
case 9:
diff -ru vtun-3.0.1/linkfd.c vtun-3.0.2/linkfd.c
--- vtun-3.0.1/linkfd.c 2006-12-11 10:55:06.000000000 +0300
+++ vtun-3.0.2/linkfd.c 2007-10-18 20:26:17.000000000 +0400
@@ -175,20 +175,38 @@
linker_term = VTUN_SIG_HUP;
}
-/* Statistic dump */
+/* Statistic dump and keep-alive monitor */
+static volatile sig_atomic_t ka_need_verify = 0;
+static time_t stat_timer = 0, ka_timer = 0;
+
void sig_alarm(int sig)
{
- static time_t tm;
+ static time_t tm_old, tm = 0;
static char stm[20];
-
+
+ tm_old = tm;
tm = time(NULL);
- strftime(stm, sizeof(stm)-1, "%b %d %H:%M:%S", localtime(&tm));
- fprintf(lfd_host->stat.file,"%s %lu %lu %lu %lu\n", stm,
- lfd_host->stat.byte_in, lfd_host->stat.byte_out,
- lfd_host->stat.comp_in, lfd_host->stat.comp_out);
-
- alarm(VTUN_STAT_IVAL);
-}
+
+ if( (lfd_host->flags & VTUN_KEEP_ALIVE) && (ka_timer -= tm-tm_old) <= 0){
+ ka_need_verify = 1;
+ ka_timer = lfd_host->ka_interval
+ + 1; /* We have to complete select() on idle */
+ }
+
+ if( (lfd_host->flags & VTUN_STAT) && (stat_timer -= tm-tm_old) <= 0){
+ strftime(stm, sizeof(stm)-1, "%b %d %H:%M:%S", localtime(&tm));
+ fprintf(lfd_host->stat.file,"%s %lu %lu %lu %lu\n", stm,
+ lfd_host->stat.byte_in, lfd_host->stat.byte_out,
+ lfd_host->stat.comp_in, lfd_host->stat.comp_out);
+ stat_timer = VTUN_STAT_IVAL;
+ }
+
+ if ( ka_timer*stat_timer ){
+ alarm( (ka_timer < stat_timer) ? ka_timer : stat_timer );
+ } else {
+ alarm( (ka_timer) ? ka_timer : stat_timer );
+ }
+}
static void sig_usr1(int sig)
{
@@ -234,6 +252,21 @@
else
continue;
}
+
+ if( ka_need_verify ){
+ if( idle > lfd_host->ka_maxfail ){
+ vtun_syslog(LOG_INFO,"Session %s network timeout", lfd_host->host);
+ break;
+ }
+ if (idle++ > 0) { /* No input frames, check connection with ECHO */
+ if( proto_write(fd1, buf, VTUN_ECHO_REQ) < 0 ){
+ vtun_syslog(LOG_ERR,"Failed to send ECHO_REQ");
+ break;
+ }
+ }
+ ka_need_verify = 0;
+ }
+
if (send_a_packet)
{
send_a_packet = 0;
@@ -245,35 +278,11 @@
break;
lfd_host->stat.comp_out += tmplen;
}
- if( !len ){
- if (send_a_packet)
- {
- send_a_packet = 0;
- tmplen = 1;
- lfd_host->stat.byte_out += tmplen;
- if( (tmplen=lfd_run_down(tmplen,buf,&out)) == -1 )
- break;
- if( tmplen && proto_write(fd1, out, tmplen) < 0 )
- break;
- lfd_host->stat.comp_out += tmplen;
- }
- /* We are idle, lets check connection */
- if( lfd_host->flags & VTUN_KEEP_ALIVE ){
- if( ++idle > lfd_host->ka_failure ){
- vtun_syslog(LOG_INFO,"Session %s network timeout",
lfd_host->host);
- break;
- }
- /* Send ECHO request */
- if( proto_write(fd1, buf, VTUN_ECHO_REQ) < 0 )
- break;
- }
- continue;
- }
/* Read frames from network(fd1), decode and pass them to
* the local device (fd2) */
if( FD_ISSET(fd1, &fdset) && lfd_check_up() ){
- idle = 0;
+ idle = 0; ka_need_verify = 0;
if( (len=proto_read(fd1, buf)) <= 0 )
break;
@@ -292,7 +301,7 @@
continue;
}
if( fl==VTUN_ECHO_REP ){
- /* Just ignore ECHO reply */
+ /* Just ignore ECHO reply, ka_need_verify==0 already */
continue;
}
if( fl==VTUN_CONN_CLOSE ){
@@ -380,6 +389,15 @@
sa.sa_handler=sig_hup;
sigaction(SIGHUP,&sa,&sa_oldhup);
+ /* Initialize keep-alive timer */
+ if( host->flags & (VTUN_STAT|VTUN_KEEP_ALIVE) ){
+ sa.sa_handler=sig_alarm;
+ sigaction(SIGALRM,&sa,NULL);
+
+ alarm( (host->ka_interval < VTUN_STAT_IVAL) ?
+ host->ka_interval : VTUN_STAT_IVAL );
+ }
+
/* Initialize statstic dumps */
if( host->flags & VTUN_STAT ){
char file[40];
@@ -392,7 +410,6 @@
sprintf(file,"%s/%.20s", VTUN_STAT_DIR, host->host);
if( (host->stat.file=fopen(file, "a")) ){
setvbuf(host->stat.file, NULL, _IOLBF, 0);
- alarm(VTUN_STAT_IVAL);
} else
vtun_syslog(LOG_ERR, "Can't open stats file %s", file);
}
@@ -401,7 +418,7 @@
lfd_linker();
- if( host->flags & VTUN_STAT ){
+ if( host->flags & (VTUN_STAT|VTUN_KEEP_ALIVE) ){
alarm(0);
if (host->stat.file)
fclose(host->stat.file);
diff -ru vtun-3.0.1/main.c vtun-3.0.2/main.c
--- vtun-3.0.1/main.c 2006-12-11 10:55:06.000000000 +0300
+++ vtun-3.0.2/main.c 2007-10-17 20:52:07.000000000 +0400
@@ -83,7 +83,7 @@
default_host.multi = VTUN_MULTI_ALLOW;
default_host.timeout = VTUN_CONNECT_TIMEOUT;
default_host.ka_interval = 30;
- default_host.ka_failure = 4;
+ default_host.ka_maxfail = 4;
default_host.loc_fd = default_host.rmt_fd = -1;
/* Start logging to syslog and stderr */
diff -ru vtun-3.0.1/vtund.conf vtun-3.0.2/vtund.conf
--- vtun-3.0.1/vtund.conf 2006-12-11 10:55:06.000000000 +0300
+++ vtun-3.0.2/vtund.conf 2007-10-17 20:09:43.000000000 +0400
@@ -117,6 +117,10 @@
# keepalive - Enable 'yes' or disable 'no' connection
# keep-alive. Ignored by the client.
#
+# May be in form 'interval:count', where 'interval' is the
+# period of connection checks, and 'count' is the maximum
+# number of retries. Indeed 'yes' = '30:4'.
+#
# -----------
# timeout - Connect timeout.
#
diff -ru vtun-3.0.1/vtund.conf.5 vtun-3.0.2/vtund.conf.5
--- vtun-3.0.1/vtund.conf.5 2006-12-11 10:55:06.000000000 +0300
+++ vtun-3.0.2/vtund.conf.5 2007-10-18 17:25:50.000000000 +0400
@@ -166,9 +166,11 @@
This option ignored by the client.
.IP \fBencrypt\ \fByes\fR|\fBno\fR
enable or disable encryption. This option ignored by the client.
-.IP \fBkeepalive\ \fByes\fR|\fBno\fR
-enable or disable connection keep-alive.
-This option is ignored by the client.
+.IP \fBkeepalive\ \fByes\fR|\fBno\fR|\fIinterval\fB:\fIcount\fR
+enable or disable connection keep-alive. Time \fIinterval\fR is a period
+between connection checks, in seconds, and \fIcount\fR is the maximum number
+of retries (\fByes\fR = \fI30\fB:\fI4\fR).
+This option is ignored by the server.
.IP \fBstat\ \fByes\fR|\fBno\fR
enable or disable statistics. If enabled \fBvtund\fR(8) will log
statistic counters to /var/log/vtund/session_X every 5 minutes.
diff -ru vtun-3.0.1/vtun.h vtun-3.0.2/vtun.h
--- vtun-3.0.1/vtun.h 2006-12-11 10:55:06.000000000 +0300
+++ vtun-3.0.2/vtun.h 2007-10-17 20:52:07.000000000 +0400
@@ -107,7 +107,7 @@
/* Keep Alive */
int ka_interval;
- int ka_failure;
+ int ka_maxfail;
/* Source address */
struct vtun_addr src_addr;
------------------------------------------------------------------------