PR/39233: Taylor R Campbeel: OpenSSH fails to initialize tun(4) tunnels

correctly.
This commit is contained in:
christos 2008-09-17 15:45:50 +00:00
parent ab6abfafd3
commit 7a75c9a543
1 changed files with 27 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: misc.c,v 1.21 2008/04/06 23:38:19 christos Exp $ */
/* $NetBSD: misc.c,v 1.22 2008/09/17 15:45:50 christos Exp $ */
/* $OpenBSD: misc.c,v 1.67 2008/01/01 08:47:04 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -26,13 +26,14 @@
*/
#include "includes.h"
__RCSID("$NetBSD: misc.c,v 1.21 2008/04/06 23:38:19 christos Exp $");
__RCSID("$NetBSD: misc.c,v 1.22 2008/09/17 15:45:50 christos Exp $");
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@ -640,17 +641,19 @@ int
tun_open(int tun, int mode)
{
struct ifreq ifr;
char name[100];
int fd = -1, sock;
int fd = -1, sock, flag;
const char *tunbase = mode == SSH_TUNMODE_ETHERNET ? "tap" : "tun";
/* Open the tunnel device */
if (tun <= SSH_TUNID_MAX) {
snprintf(name, sizeof(name), "/dev/tun%d", tun);
fd = open(name, O_RDWR);
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name),
"/dev/%s%d", tunbase, tun);
fd = open(ifr.ifr_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)
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name),
"/dev/%s%d", tunbase, tun);
if ((fd = open(ifr.ifr_name, O_RDWR)) >= 0)
break;
}
} else {
@ -659,20 +662,31 @@ tun_open(int tun, int mode)
}
if (fd < 0) {
debug("%s: %s open failed: %s", __func__, name, strerror(errno));
debug("%s: %s open failed: %s", __func__, ifr.ifr_name,
strerror(errno));
return (-1);
}
debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
/* Turn on tunnel headers */
flag = 1;
if (mode != SSH_TUNMODE_ETHERNET &&
ioctl(fd, TUNSIFHEAD, &flag) == -1) {
debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd,
strerror(errno));
close(fd);
return -1;
}
debug("%s: %s mode %d fd %d", __func__, ifr.ifr_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 0
/* Set interface mode */
ifr.ifr_flags &= ~IFF_UP;
if (mode == SSH_TUNMODE_ETHERNET)
@ -681,6 +695,7 @@ tun_open(int tun, int mode)
ifr.ifr_flags &= ~IFF_LINK0;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
goto failed;
#endif
/* Bring interface up */
ifr.ifr_flags |= IFF_UP;
@ -695,7 +710,7 @@ tun_open(int tun, int mode)
close(fd);
if (sock >= 0)
close(sock);
debug("%s: failed to set %s mode %d: %s", __func__, name,
debug("%s: failed to set %s mode %d: %s", __func__, ifr.ifr_name,
mode, strerror(errno));
return (-1);
}