diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-12-08 18:34:12 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-12-08 18:34:12 +0000 |
commit | 71e9c1668d8823e2153147c31d4d55045ff4112c (patch) | |
tree | 4add4b6e62b561c08001e9bd96fed4da3229880c /usr.bin/ssh/misc.c | |
parent | b0e765b15c8ba03873c4d8f9a97dc1bc518b24f2 (diff) |
two changes to the new ssh tunnel support. this breaks compatibility
with the initial commit but is required for a portable approach.
- make the tunnel id u_int and platform friendly, use predefined types.
- support configuration of layer 2 (ethernet) or layer 3
(point-to-point, default) modes. configuration is done using the
Tunnel (yes|point-to-point|ethernet|no) option is ssh_config(5) and
restricted by the PermitTunnel (yes|point-to-point|ethernet|no) option
in sshd_config(5).
ok djm@, man page bits by jmc@
Diffstat (limited to 'usr.bin/ssh/misc.c')
-rw-r--r-- | usr.bin/ssh/misc.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/usr.bin/ssh/misc.c b/usr.bin/ssh/misc.c index dc715ac6778..d70e199c578 100644 --- a/usr.bin/ssh/misc.c +++ b/usr.bin/ssh/misc.c @@ -24,7 +24,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: misc.c,v 1.36 2005/12/06 22:38:27 reyk Exp $"); +RCSID("$OpenBSD: misc.c,v 1.37 2005/12/08 18:34:11 reyk Exp $"); #include "misc.h" #include "log.h" @@ -196,7 +196,7 @@ a2tun(const char *s, int *remote) int tun; if (remote != NULL) { - *remote = -1; + *remote = SSH_TUNID_ANY; sp = xstrdup(s); if ((ep = strchr(sp, ':')) == NULL) { xfree(sp); @@ -206,15 +206,15 @@ a2tun(const char *s, int *remote) *remote = a2tun(ep, NULL); tun = a2tun(sp, NULL); xfree(sp); - return (tun); + return (*remote == SSH_TUNID_ERR ? *remote : tun); } if (strcasecmp(s, "any") == 0) - return (-1); + return (SSH_TUNID_ANY); - tun = strtonum(s, 0, INT_MAX, &errstr); - if (errstr != NULL || tun < -1) - return (-2); + tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); + if (errstr != NULL) + return (SSH_TUNID_ERR); return (tun); } @@ -533,27 +533,60 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, } int -tun_open(int tun) +tun_open(int tun, int mode) { + struct ifreq ifr; char name[100]; - int i, fd; + int fd = -1, sock; - if (tun > -1) { + /* Open the tunnel device */ + if (tun <= SSH_TUNID_MAX) { snprintf(name, sizeof(name), "/dev/tun%d", tun); - if ((fd = open(name, O_RDWR)) >= 0) { - debug("%s: %s: %d", __func__, name, fd); - return (fd); + fd = open(name, O_RDWR); + } else if (tun == SSH_TUNID_ANY) { + for (tun = 100; tun >= 0; tun--) { + snprintf(name, sizeof(name), "/dev/tun%d", tun); + if ((fd = open(name, O_RDWR)) >= 0) + break; } } 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: invalid tunnel %u\n", __func__, tun); + return (-1); + } + + if (fd < 0) { + debug("%s: %s open failed: %s", __func__, name, strerror(errno)); + return (-1); + } + + 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), "tun%d", tun); + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) + goto failed; + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) + goto failed; + if (mode == SSH_TUNMODE_ETHERNET) { + ifr.ifr_flags |= IFF_LINK0; + if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) + goto failed; } - debug("%s: %s failed: %s", __func__, name, strerror(errno)); + 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); } |