summaryrefslogtreecommitdiff
path: root/usr.bin/ssh/misc.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2005-12-08 18:34:12 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2005-12-08 18:34:12 +0000
commit71e9c1668d8823e2153147c31d4d55045ff4112c (patch)
tree4add4b6e62b561c08001e9bd96fed4da3229880c /usr.bin/ssh/misc.c
parentb0e765b15c8ba03873c4d8f9a97dc1bc518b24f2 (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.c75
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);
}