From 0f6cb079798638b631e42bed0d8e03771a018aec Mon Sep 17 00:00:00 2001 From: djm Date: Sun, 1 Jan 2006 08:47:05 +0000 Subject: [PATCH] - (djm) [Makefile.in configure.ac includes.h misc.c] [openbsd-compat/port-tun.c openbsd-compat/port-tun.h] Add support for tunnel forwarding for FreeBSD and NetBSD. NetBSD's support is limited to IPv4 tunnels only, and most versions don't support the tap(4) device at all. --- ChangeLog | 7 +++ Makefile.in | 2 +- configure.ac | 10 +++- includes.h | 3 -- misc.c | 2 +- openbsd-compat/port-tun.c | 98 ++++++++++++++++++++++++++++++++++++++- openbsd-compat/port-tun.h | 2 +- 7 files changed, 116 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index f0e56954..66051492 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +20060101 + - (djm) [Makefile.in configure.ac includes.h misc.c] + [openbsd-compat/port-tun.c openbsd-compat/port-tun.h] Add support + for tunnel forwarding for FreeBSD and NetBSD. NetBSD's support is + limited to IPv4 tunnels only, and most versions don't support the + tap(4) device at all. + 20051229 - (djm) OpenBSD CVS Sync - stevesk@cvs.openbsd.org 2005/12/28 22:46:06 diff --git a/Makefile.in b/Makefile.in index abbe6244..15a165a8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -139,7 +139,7 @@ sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBS) scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) diff --git a/configure.ac b/configure.ac index e24cc4de..ff71931a 100644 --- a/configure.ac +++ b/configure.ac @@ -346,10 +346,18 @@ mips-sony-bsd|mips-sony-newsos4) if test "x$withval" != "xno" ; then need_dash_r=1 fi + AC_DEFINE(SSH_TUN_FREEBSD, 1, [Open tunnel devices the FreeBSD way]) + AC_CHECK_HEADER([net/if_tap.h], , + AC_DEFINE(SSH_TUN_NO_L2, 1, [No layer 2 tunnel support])) + AC_DEFINE(SSH_TUN_PREPEND_AF, 1, + [Prepend the address family to IP tunnel traffic]) ;; *-*-freebsd*) check_for_libcrypt_later=1 AC_DEFINE(LOCKED_PASSWD_PREFIX, "*LOCKED*", [Account locked with pw(1)]) + AC_DEFINE(SSH_TUN_FREEBSD, 1, [Open tunnel devices the FreeBSD way]) + AC_CHECK_HEADER([net/if_tap.h], , + AC_DEFINE(SSH_TUN_NO_L2, 1, [No layer 2 tunnel support])) ;; *-*-bsdi*) AC_DEFINE(SETEUID_BREAKS_SETUID) @@ -369,7 +377,7 @@ mips-sony-bsd|mips-sony-newsos4) *-*-openbsd*) AC_DEFINE(HAVE_ATTRIBUTE__SENTINEL__, 1, [OpenBSD's gcc has sentinel]) AC_DEFINE(HAVE_ATTRIBUTE__BOUNDED__, 1, [OpenBSD's gcc has bounded]) - AC_DEFINE(SSH_TUN_BSD, 1, [Open tunnel devices the BSD way]) + AC_DEFINE(SSH_TUN_OPENBSD, 1, [Open tunnel devices the OpenBSD way]) ;; *-*-solaris*) if test "x$withval" != "xno" ; then diff --git a/includes.h b/includes.h index cf2d6c69..808d5dc9 100644 --- a/includes.h +++ b/includes.h @@ -148,9 +148,6 @@ static /**/const char *const rcsid[] = { (const char *)rcsid, "\100(#)" msg } #include /* For IPv6 macros */ #include /* For IPTOS macros */ #include -#ifdef HAVE_NET_IF_H -# include -#endif #include #if defined(HAVE_NETDB_H) # include diff --git a/misc.c b/misc.c index 4141e6c4..76dbf40e 100644 --- a/misc.c +++ b/misc.c @@ -543,7 +543,7 @@ tun_open(int tun, int mode) { #if defined(CUSTOM_SYS_TUN_OPEN) return (sys_tun_open(tun, mode)); -#elif defined(SSH_TUN_BSD) +#elif defined(SSH_TUN_OPENBSD) struct ifreq ifr; char name[100]; int fd = -1, sock; diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-tun.c index 479b46b7..00a0442b 100644 --- a/openbsd-compat/port-tun.c +++ b/openbsd-compat/port-tun.c @@ -89,6 +89,88 @@ sys_tun_open(int tun, int mode) } #endif /* SSH_TUN_LINUX */ +#ifdef SSH_TUN_FREEBSD +#include +#include +#include + +int +sys_tun_open(int tun, int mode) +{ + struct ifreq ifr; + char name[100]; + int fd = -1, sock, flag; + const char *tunbase = "tun"; + + if (mode == SSH_TUNMODE_ETHERNET) { +#ifdef SSH_TUN_NO_L2 + debug("%s: no layer 2 tunnelling support", __func__); + return (-1); +#else + tunbase = "tap"; +#endif + } + + /* Open the tunnel device */ + if (tun <= SSH_TUNID_MAX) { + snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); + fd = open(name, O_RDWR); + } else if (tun == SSH_TUNID_ANY) { + for (tun = 100; tun >= 0; tun--) { + snprintf(name, sizeof(name), "/dev/%s%d", + tunbase, tun); + if ((fd = open(name, O_RDWR)) >= 0) + break; + } + } else { + debug("%s: invalid tunnel %u\n", __func__, tun); + return (-1); + } + + if (fd < 0) { + debug("%s: %s open failed: %s", __func__, name, + strerror(errno)); + return (-1); + } + + /* Turn on tunnel headers */ + flag = 1; +#if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) + if (mode != SSH_TUNMODE_ETHERNET && + ioctl(fd, TUNSIFHEAD, &flag) == -1) { + debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd, + strerror(errno)); + close(fd); + } +#endif + + debug("%s: %s mode %d fd %d", __func__, name, mode, fd); + + /* Set the tunnel device operation mode */ + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) + goto failed; + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) + goto failed; + ifr.ifr_flags |= IFF_UP; + if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) + goto failed; + + close(sock); + return (fd); + + failed: + if (fd >= 0) + close(fd); + if (sock >= 0) + close(sock); + debug("%s: failed to set %s mode %d: %s", __func__, name, + mode, strerror(errno)); + return (-1); +} +#endif /* SSH_TUN_FREEBSD */ + /* * System-specific channel filters */ @@ -102,16 +184,29 @@ sys_tun_infilter(struct Channel *c, char *buf, int len) { #if defined(SSH_TUN_PREPEND_AF) char rbuf[CHAN_RBUF]; + struct ip *iph; #endif u_int32_t *af; char *ptr = buf; #if defined(SSH_TUN_PREPEND_AF) - if (len > (int)(sizeof(rbuf) - sizeof(*af))) + if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) return (-1); ptr = (char *)&rbuf[0]; bcopy(buf, ptr + sizeof(u_int32_t), len); len += sizeof(u_int32_t); + af = (u_int32_t *)ptr; + + iph = (struct ip *)(ptr + sizeof(u_int32_t)); + switch (iph->ip_v) { + case 6: + *af = AF_INET6; + break; + case 4: + default: + *af = AF_INET; + break; + } #endif #if defined(SSH_TUN_COMPAT_AF) @@ -124,6 +219,7 @@ sys_tun_infilter(struct Channel *c, char *buf, int len) else *af = htonl(OPENBSD_AF_INET); #endif + buffer_put_string(&c->input, ptr, len); return (0); } diff --git a/openbsd-compat/port-tun.h b/openbsd-compat/port-tun.h index 942610c6..86d9272b 100644 --- a/openbsd-compat/port-tun.h +++ b/openbsd-compat/port-tun.h @@ -19,7 +19,7 @@ #include "channels.h" -#if defined(SSH_TUN_LINUX) +#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) # define CUSTOM_SYS_TUN_OPEN int sys_tun_open(int, int); #endif -- 2.45.2