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; ------------------------------------------------------------------------