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;

------------------------------------------------------------------------



Reply via email to