version 1.36, 2005/12/06 22:38:27 |
version 1.37, 2005/12/08 18:34:11 |
|
|
int tun; |
int tun; |
|
|
if (remote != NULL) { |
if (remote != NULL) { |
*remote = -1; |
*remote = SSH_TUNID_ANY; |
sp = xstrdup(s); |
sp = xstrdup(s); |
if ((ep = strchr(sp, ':')) == NULL) { |
if ((ep = strchr(sp, ':')) == NULL) { |
xfree(sp); |
xfree(sp); |
|
|
*remote = a2tun(ep, NULL); |
*remote = a2tun(ep, NULL); |
tun = a2tun(sp, NULL); |
tun = a2tun(sp, NULL); |
xfree(sp); |
xfree(sp); |
return (tun); |
return (*remote == SSH_TUNID_ERR ? *remote : tun); |
} |
} |
|
|
if (strcasecmp(s, "any") == 0) |
if (strcasecmp(s, "any") == 0) |
return (-1); |
return (SSH_TUNID_ANY); |
|
|
tun = strtonum(s, 0, INT_MAX, &errstr); |
tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); |
if (errstr != NULL || tun < -1) |
if (errstr != NULL) |
return (-2); |
return (SSH_TUNID_ERR); |
|
|
return (tun); |
return (tun); |
} |
} |
|
|
} |
} |
|
|
int |
int |
tun_open(int tun) |
tun_open(int tun, int mode) |
{ |
{ |
|
struct ifreq ifr; |
char name[100]; |
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); |
snprintf(name, sizeof(name), "/dev/tun%d", tun); |
if ((fd = open(name, O_RDWR)) >= 0) { |
fd = open(name, O_RDWR); |
debug("%s: %s: %d", __func__, name, fd); |
} else if (tun == SSH_TUNID_ANY) { |
return (fd); |
for (tun = 100; tun >= 0; tun--) { |
|
snprintf(name, sizeof(name), "/dev/tun%d", tun); |
|
if ((fd = open(name, O_RDWR)) >= 0) |
|
break; |
} |
} |
} else { |
} else { |
for (i = 100; i >= 0; i--) { |
debug("%s: invalid tunnel %u\n", __func__, tun); |
snprintf(name, sizeof(name), "/dev/tun%d", i); |
return (-1); |
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)); |
|
|
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; |
|
} |
|
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); |
return (-1); |
} |
} |
|
|