From spatula@shell3.ba.best.com Sat Aug 21 15:38:52 1999
Return-Path: <spatula@shell3.ba.best.com>
Received: from shell3.ba.best.com (shell3.ba.best.com [206.184.139.134])
	by hub.freebsd.org (Postfix) with ESMTP id E1DE615461
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 21 Aug 1999 15:38:51 -0700 (PDT)
	(envelope-from spatula@shell3.ba.best.com)
Received: (from spatula@localhost)
	by shell3.ba.best.com (8.9.3/8.9.2/best.sh) id PAA17603;
	Sat, 21 Aug 1999 15:38:16 -0700 (PDT)
Message-Id: <199908212238.PAA17603@shell3.ba.best.com>
Date: Sat, 21 Aug 1999 15:38:16 -0700 (PDT)
From: freebsd@spatula.net
Sender: spatula@shell3.ba.best.com
Reply-To: freebsd@spatula.net
To: FreeBSD-gnats-submit@freebsd.org
Subject: enhancements and fixes for nos-tun
X-Send-Pr-Version: 3.2

>Number:         13309
>Category:       bin
>Synopsis:       [patch] Fixes to nos-tun(8)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          suspended
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Aug 21 15:40:01 PDT 1999
>Closed-Date:    
>Last-Modified:  Sun May 06 00:41:00 GMT 2007
>Originator:     Nick Johnson
>Release:        FreeBSD 4.0-CURRENT i386
>Organization:
>Environment:

	

>Description:

The return values from write and send are not checked in nos-tun.  In
addition, functionality to shut down & re-set-up a link when sends repeatedly
fail is nice, especially in the case of a dynamic IP/DNS environment.

Code structure left a bit to be desired.

	

>How-To-Repeat:

	

>Fix:
	
Patches to nos-tun.c:

--- nos-tun.c	Tue Jul 27 13:48:38 1999
+++ nos-tun.c	Tue Jul 27 12:27:21 1999
@@ -55,6 +55,13 @@
  *
  */
 
+/*
+ * 19990727 - Nick Johnson <freebsd@spatula.net>
+ * Added -r and -w flags, cleaned up the code a bit,
+ * made writes more robust (return values were not being
+ * checked)
+ */
+
 #ifndef lint
 static const char rcsid[] =
 	"$Id: nos-tun.c,v 1.5 1999/03/29 13:58:27 phk Exp $";
@@ -186,7 +193,7 @@
   return(1);
 }
 
-void Finish(int signum)
+void Cleanup()
 {
   int s;
 
@@ -227,8 +234,44 @@
   close(s);
 closing_tun:
   close(tun);
+}
+
+void Finish() 
+{
+  Cleanup();
   closelog();
-  exit(signum);
+}
+
+void sighandle(int signum) 
+{
+   Finish();
+   exit(signum);
+}
+
+int Setup (char *devname, struct sockaddr *t_laddr, char *to_point,
+            struct sockaddr *whereto, char *target, struct sockaddr_in *to,
+            int protnum)            
+{
+  if(tun_open(devname, t_laddr, to_point)) {
+    closelog();
+    return(3);
+  }
+
+  to = (struct sockaddr_in *)&whereto;
+  if(Set_address(target, to))
+    return(4);
+
+  if ((net = socket(AF_INET, SOCK_RAW, protnum)) < 0) {
+    syslog(LOG_ERR,"can't open socket - %m");
+    return(5);
+  }
+
+  if (connect(net,whereto,sizeof(struct sockaddr_in)) < 0 ) {
+    syslog(LOG_ERR,"can't connect to target - %m");
+    close(net);
+    return(6);
+  }
+  return(0);
 }
 
 int main (int argc, char **argv)
@@ -252,8 +295,15 @@
   fd_set rfds, wfds, efds;          /* File descriptors for select() */
   int nfds;                         /* Return from select() */
 
+  ssize_t woff, wsize;              /* offset & Return values for write */
+  int reset = 0;                    /* try to re-setup when writes fail */
+  int sleeplen = 60;                /* how long to sleep before retrying */
+  int retries = 0;                  /* how many times to try to set up */
+  int werror = 0;                   /* write error flag */
+  int retcnt = 0;                   /* retry counter */
+  int ret;                          /* generic return value */
 
-  while ((c = getopt(argc, argv, "d:s:t:p:")) != -1) {
+  while ((c = getopt(argc, argv, "d:s:t:p:r:w:")) != -1) {
     switch (c) {
     case 'd':
       to_point = optarg;
@@ -267,6 +317,17 @@
     case 'p':
       protocol = optarg;
       break;
+    case 'r':
+      reset = 1;
+      if (optarg[0] != ':')
+        retries = atoi(optarg);
+      break;
+    case 'w':
+      if (optarg[0] != ':')
+        sleeplen = atoi(optarg);
+      else
+        usage();
+      break;
     }
   }
   argc -= optind;
@@ -292,35 +353,47 @@
     exit(2);
   }
 
-  if(tun_open(devname, &t_laddr, to_point)) {
-    closelog();
-    exit(3);
-  }
-
-  to = (struct sockaddr_in *)&whereto;
-  if(Set_address(target, to))
-    Finish(4);
-
-  if ((net = socket(AF_INET, SOCK_RAW, protnum)) < 0) {
-    syslog(LOG_ERR,"can't open socket - %m");
-    Finish(5);
-  }
-
-  if (connect(net,&whereto,sizeof(struct sockaddr_in)) < 0 ) {
-    syslog(LOG_ERR,"can't connect to target - %m");
-    close(net);
-    Finish(6);
-  }
-
   /*  Demonize it */
   daemon(0,0);
 
   /* Install signal handlers */
-  (void)signal(SIGHUP,Finish);
-  (void)signal(SIGINT,Finish);
-  (void)signal(SIGTERM,Finish);
+  (void)signal(SIGHUP,sighandle);
+  (void)signal(SIGINT,sighandle);
+  (void)signal(SIGTERM,sighandle);
+
+  /* Set up the tunnel */
+  if ((ret=Setup(devname, &t_laddr, to_point, &whereto, target, to, protnum))) {
+    Finish();
+    exit(ret);
+  }
 
   for (;;) {
+    fortop:
+    if (werror) {
+      if (!reset) {
+        syslog(LOG_ERR,"write error, exiting");
+        Finish();
+        exit(8);
+      }
+      /* We got a write error and we're trying to maintain the tunnel */
+      /* Clean out the old and try to set it up again */
+      do {
+        Cleanup();
+        syslog(LOG_NOTICE,"waiting to retry tunnel setup");
+        sleep(sleeplen);
+        retcnt++;
+      } while((ret = Setup(devname, &t_laddr, to_point, &whereto, target, 
+                           to, protnum)) 
+               && (retcnt < retries) 
+               && (werror < retries));
+      if (ret) {
+        syslog(LOG_ERR,"unable to re-establish tunnel");
+        Finish();
+        exit(8);
+      } else {
+        retcnt = 0; /* werror does not get reset until we successfully write */
+      }
+    }
     /* Set file descriptors for select() */
     FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
     FD_SET(tun,&rfds); FD_SET(net,&rfds);
@@ -329,12 +402,14 @@
     if(nfds < 0) {
       syslog(LOG_ERR,"interrupted select");
       close(net);
-      Finish(7);
+      Finish();
+      exit(7);
     }
     if(nfds == 0) {         /* Impossible ? */
       syslog(LOG_ERR,"timeout in select");
       close(net);
-      Finish(8);
+      Finish();
+      exit(8);
     }
 
 
@@ -346,7 +421,17 @@
 	/* ... skip encapsulation headers ... */
 	ipoff = (ip->ip_hl << 2);
 	/* ... and write to tun-device */
-	write(tun,buf+ipoff,len-ipoff);
+	woff = 0;
+        while (woff < (len-ipoff)) {
+	   if((wsize = write(tun, buf+ipoff+woff, len-ipoff-woff))<1) {
+             syslog(LOG_ERR, "can't send - %m");
+             werror++;
+             goto fortop;
+           } else {
+             werror = 0;
+           }
+           woff += wsize;
+        }
       }
     }
 
@@ -354,8 +439,16 @@
       /* Read from tun ... */
       len = read(tun, buf, sizeof(buf));
       /* ... and send to network */
-      if(send(net, buf, len,0) <= 0) {
-	syslog(LOG_ERR,"can't send - %m");
+      woff = 0;
+      while (woff < len) {
+        if((wsize = send(net, buf+woff, len-woff,0)) < 1) {
+          syslog(LOG_ERR,"can't send - %m");
+          werror++;
+          goto fortop;
+        } else {
+          werror = 0;
+        }
+        woff += wsize;
       }
     }
   }
@@ -365,7 +458,7 @@
 usage()
 {
 	fprintf(stderr,
-"usage: nos_tun -t <tun_name> -s <source_addr> -d <dest_addr> -p <protocol_number> <target_addr>\n");
+"usage: nos_tun -t <tun_name> -s <source_addr> -d <dest_addr> -p <protocol_number> [-r [retry count] -w <retry delay>] <target_addr>\n");
 	exit(1);
 }

Patches to nos-tun.8:


--- nos-tun.8	Tue Jul 27 13:48:37 1999
+++ nos-tun.8	Tue Jul 27 13:50:58 1999
@@ -24,6 +24,10 @@
 .Ar destination
 .Fl p
 .Ar protocol_number
+.Fl r
+.Ar retry_count
+.Fl w
+.Ar retry_delay
 .Ar target
 .Sh DESCRIPTION
 .Nm Nos-tun
@@ -46,20 +50,34 @@
 and
 .Ar destination
 are the addresses used on the tunnel device.
-If you configure the tunnel against a cisco router, use a netmask of
+If you configure the tunnel against a Cisco router, use a netmask of
 .Dq 255.255.255.252
-on the cisco.  This is because the tunnel is a point-to-point interface
+on the Cisco router.  This is because the tunnel is a point-to-point interface
 in the
 .Bx Free
-end, a concept cisco doesn't really implement.
+end, a concept Cisco doesn't really implement.  Destination may be 
+a hostname.
 .Pp
 .Ar Protocol number
 sets tunnel mode. Original KA9Q NOS uses 94 but many peoples use 4
 in worldwide backbone of ampr.org.
 .Pp
+.Ar Retry count
+if provided, limits the number of times 
+.Nm nos-tun
+will attempt to re-establish a tunnel when a connection fails.  Use 0
+for infinite retries.  The default is 10.  When performing a retry, the
+tunnel is shut down and rebuilt, performing name lookups again if 
+applicable.  This allows for building tunnels with static addresses
+across links with dynamic addresses.
+.Pp
+.Ar Retry delay
+Number of seconds to sleep before trying to re-establish a tunnel.
+The default is 60 seconds.
+.Pp
 .Ar Target
 is the address of the remote tunnel device, this must match the source
-address set on the remote end.
+address set on the remote end.  Target may be a hostname.
 .Sh EXAMPLES
 This end, a
 .Bx Free
@@ -68,7 +86,7 @@
 nos-tun -t /dev/tun0 -s 192.168.61.1 -d 192.168.61.2 192.168.56.45
 .Ed
 .Pp
-Remote cisco on address 192.168.56.45:
+Remote Cisco router on address 192.168.56.45:
 .Bd -literal -offset indent 4m 
 interface tunnel 0
 ip address 192.168.61.2 255.255.255.252
@@ -85,3 +103,5 @@
 wrote the man-page.
 .An Isao SEKI Aq iseki@gongon.com
 added a new flag, IP protocol number.
+.An Nick Johnson
+added retries, -r and -w flags.
 
	


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: gnats-admin->freebsd-bugs 
Responsible-Changed-By: hoek 
Responsible-Changed-When: Sun Aug 22 13:07:44 PDT 1999 
Responsible-Changed-Why:  
Misfiled PR 

From: Tim Vanderhoek <tim@ppp18344.on.bellglobal.com>
To: freebsd-gnats-submit@freebsd.org, freebsd@spatula.net
Cc:  
Subject: Re: pending/13309: nos-tun doesn't check return values%2
Date: Sun, 22 Aug 1999 16:23:30 -0400 (EDT)

 >
 >+/*
 >+ * 19990727 - Nick Johnson <freebsd@spatula.net>
 >+ * Added -r and -w flags, cleaned up the code a bit,
 >+ * made writes more robust (return values were not being
 >+ * checked)
 >+ */
 
 Don't include these type of comments.  We have cvs do this for us.
 
 
 >-void Finish(int signum)
 >+void Cleanup()
 > {
 
 I guess there's no prototype for this function.
 
 
 >+  if(Set_address(target, to))
 >+    return(4);
 
 To maintain consistency with the existing nos-tun.c, consider using
 a "{ ... }" block even if it's not needed.
 
 
 >-end, a concept cisco doesn't really implement.
 >+end, a concept Cisco doesn't really implement.  Destination may be
 >+a hostname.
 
 To make keeping the translated manpages synchronized with their
 English versions easier, don't gratuitously change a line.  The
 sentence you added should have been started on a new line.
 
 [Actually, there has been some suggestion that standard mdoc style is
  to start sentences on newlines in most cases...  You may consider this,
  too...  It means that future changes are clearer and easier to read ---
  once again important for people doing translation.]
 
 
 >-address set on the remote end.
 >+address set on the remote end.  Target may be a hostname.
 
 Same.
 
State-Changed-From-To: open->feedback 
State-Changed-By: iedowse 
State-Changed-When: Sun Jan 20 10:23:56 PST 2002 
State-Changed-Why:  

Is this problem still present? If so, do you have an update patch as 
per the comments in the audit trail? 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=13309 
State-Changed-From-To: feedback->open 
State-Changed-By: billf 
State-Changed-When: Mon Jan 21 12:54:27 PST 2002 
State-Changed-Why:  
these patches are still relevent 


Responsible-Changed-From-To: freebsd-bugs->billf 
Responsible-Changed-By: billf 
Responsible-Changed-When: Mon Jan 21 12:54:27 PST 2002 
Responsible-Changed-Why:  
i will work with the submitter (as i know him) to generate 
updated patches and test them. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=13309 
State-Changed-From-To: open->feedback 
State-Changed-By: linimon 
State-Changed-When: Wed Mar 14 23:00:07 UTC 2007 
State-Changed-Why:  
To submitter: are these patches still relevant? 


Responsible-Changed-From-To: billf->linimon 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Mar 14 23:00:07 UTC 2007 
Responsible-Changed-Why:  
Assignee did not respond to request for status of this PR, so reassign 
to the pool. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=13309 
State-Changed-From-To: feedback->suspended 
State-Changed-By: linimon 
State-Changed-When: Sun May 6 00:39:03 UTC 2007 
State-Changed-Why:  
Since no one responded to my request for status on this PR, just set 
it to 'suspended'. 


Responsible-Changed-From-To: linimon->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Sun May 6 00:39:03 UTC 2007 
Responsible-Changed-Why:  

http://www.freebsd.org/cgi/query-pr.cgi?pr=13309 
>Unformatted:
