- reyk@cvs.openbsd.org 2005/12/06 22:38:28
     [auth-options.c auth-options.h channels.c channels.h clientloop.c]
     [misc.c misc.h readconf.c readconf.h scp.c servconf.c servconf.h]
     [serverloop.c sftp.c ssh.1 ssh.c ssh_config ssh_config.5 sshconnect.c]
     [sshconnect.h sshd.8 sshd_config sshd_config.5]
     Add support for tun(4) forwarding over OpenSSH, based on an idea and
     initial channel code bits by markus@. This is a simple and easy way to
     use OpenSSH for ad hoc virtual private network connections, e.g.
     administrative tunnels or secure wireless access. It's based on a new
     ssh channel and works similar to the existing TCP forwarding support,
     except that it depends on the tun(4) network interface on both ends of
     the connection for layer 2 or layer 3 tunneling. This diff also adds
     support for LocalCommand in the ssh(1) client.

     ok djm@, markus@, jmc@ (manpages), tested and discussed with others
diff --git a/misc.c b/misc.c
index 27b947f..9b23e2c 100644
--- a/misc.c
+++ b/misc.c
@@ -24,7 +24,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.35 2005/09/13 23:40:07 djm Exp $");
+RCSID("$OpenBSD: misc.c,v 1.36 2005/12/06 22:38:27 reyk Exp $");
 
 #include "misc.h"
 #include "log.h"
@@ -194,6 +194,37 @@
 	return port;
 }
 
+int
+a2tun(const char *s, int *remote)
+{
+	const char *errstr = NULL;
+	char *sp, *ep;
+	int tun;
+
+	if (remote != NULL) {
+		*remote = -1;
+		sp = xstrdup(s);
+		if ((ep = strchr(sp, ':')) == NULL) {
+			xfree(sp);
+			return (a2tun(s, NULL));
+		}
+		ep[0] = '\0'; ep++;
+		*remote = a2tun(ep, NULL);
+		tun = a2tun(sp, NULL);
+		xfree(sp);
+		return (tun);
+	}
+
+	if (strcasecmp(s, "any") == 0)
+		return (-1);
+
+	tun = strtonum(s, 0, INT_MAX, &errstr);
+	if (errstr != NULL || tun < -1)
+		return (-2);
+
+	return (tun);
+}
+
 #define SECONDS		1
 #define MINUTES		(SECONDS * 60)
 #define HOURS		(MINUTES * 60)
@@ -507,6 +538,31 @@
 	return -1;
 }
 
+int
+tun_open(int tun)
+{
+	char name[100];
+	int i, fd;
+
+	if (tun > -1) {
+		snprintf(name, sizeof(name), "/dev/tun%d", tun);
+		if ((fd = open(name, O_RDWR)) >= 0)  {
+			debug("%s: %s: %d", __func__, name, fd);
+			return (fd);
+		}
+	} else {
+		for (i = 100; i >= 0; i--) {
+			snprintf(name, sizeof(name), "/dev/tun%d", i);
+			if ((fd = open(name, O_RDWR)) >= 0)  {
+				debug("%s: %s: %d", __func__, name, fd);
+				return (fd);
+			}
+		}
+	}
+	debug("%s: %s failed: %s", __func__, name, strerror(errno));
+	return (-1);
+}
+
 void
 sanitise_stdfd(void)
 {