diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 75 |
1 files changed, 54 insertions, 21 deletions
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | RCSID("$OpenBSD: misc.c,v 1.36 2005/12/06 22:38:27 reyk Exp $"); | 27 | RCSID("$OpenBSD: misc.c,v 1.37 2005/12/08 18:34:11 reyk Exp $"); |
28 | 28 | ||
29 | #include "misc.h" | 29 | #include "misc.h" |
30 | #include "log.h" | 30 | #include "log.h" |
@@ -202,7 +202,7 @@ a2tun(const char *s, int *remote) | |||
202 | int tun; | 202 | int tun; |
203 | 203 | ||
204 | if (remote != NULL) { | 204 | if (remote != NULL) { |
205 | *remote = -1; | 205 | *remote = SSH_TUNID_ANY; |
206 | sp = xstrdup(s); | 206 | sp = xstrdup(s); |
207 | if ((ep = strchr(sp, ':')) == NULL) { | 207 | if ((ep = strchr(sp, ':')) == NULL) { |
208 | xfree(sp); | 208 | xfree(sp); |
@@ -212,15 +212,15 @@ a2tun(const char *s, int *remote) | |||
212 | *remote = a2tun(ep, NULL); | 212 | *remote = a2tun(ep, NULL); |
213 | tun = a2tun(sp, NULL); | 213 | tun = a2tun(sp, NULL); |
214 | xfree(sp); | 214 | xfree(sp); |
215 | return (tun); | 215 | return (*remote == SSH_TUNID_ERR ? *remote : tun); |
216 | } | 216 | } |
217 | 217 | ||
218 | if (strcasecmp(s, "any") == 0) | 218 | if (strcasecmp(s, "any") == 0) |
219 | return (-1); | 219 | return (SSH_TUNID_ANY); |
220 | 220 | ||
221 | tun = strtonum(s, 0, INT_MAX, &errstr); | 221 | tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); |
222 | if (errstr != NULL || tun < -1) | 222 | if (errstr != NULL) |
223 | return (-2); | 223 | return (SSH_TUNID_ERR); |
224 | 224 | ||
225 | return (tun); | 225 | return (tun); |
226 | } | 226 | } |
@@ -539,27 +539,60 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, | |||
539 | } | 539 | } |
540 | 540 | ||
541 | int | 541 | int |
542 | tun_open(int tun) | 542 | tun_open(int tun, int mode) |
543 | { | 543 | { |
544 | struct ifreq ifr; | ||
544 | char name[100]; | 545 | char name[100]; |
545 | int i, fd; | 546 | int fd = -1, sock; |
546 | 547 | ||
547 | if (tun > -1) { | 548 | /* Open the tunnel device */ |
549 | if (tun <= SSH_TUNID_MAX) { | ||
548 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | 550 | snprintf(name, sizeof(name), "/dev/tun%d", tun); |
549 | if ((fd = open(name, O_RDWR)) >= 0) { | 551 | fd = open(name, O_RDWR); |
550 | debug("%s: %s: %d", __func__, name, fd); | 552 | } else if (tun == SSH_TUNID_ANY) { |
551 | return (fd); | 553 | for (tun = 100; tun >= 0; tun--) { |
554 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | ||
555 | if ((fd = open(name, O_RDWR)) >= 0) | ||
556 | break; | ||
552 | } | 557 | } |
553 | } else { | 558 | } else { |
554 | for (i = 100; i >= 0; i--) { | 559 | debug("%s: invalid tunnel %u\n", __func__, tun); |
555 | snprintf(name, sizeof(name), "/dev/tun%d", i); | 560 | return (-1); |
556 | if ((fd = open(name, O_RDWR)) >= 0) { | 561 | } |
557 | debug("%s: %s: %d", __func__, name, fd); | 562 | |
558 | return (fd); | 563 | if (fd < 0) { |
559 | } | 564 | debug("%s: %s open failed: %s", __func__, name, strerror(errno)); |
560 | } | 565 | return (-1); |
566 | } | ||
567 | |||
568 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); | ||
569 | |||
570 | /* Set the tunnel device operation mode */ | ||
571 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); | ||
572 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) | ||
573 | goto failed; | ||
574 | |||
575 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) | ||
576 | goto failed; | ||
577 | if (mode == SSH_TUNMODE_ETHERNET) { | ||
578 | ifr.ifr_flags |= IFF_LINK0; | ||
579 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | ||
580 | goto failed; | ||
561 | } | 581 | } |
562 | debug("%s: %s failed: %s", __func__, name, strerror(errno)); | 582 | ifr.ifr_flags |= IFF_UP; |
583 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | ||
584 | goto failed; | ||
585 | |||
586 | close(sock); | ||
587 | return (fd); | ||
588 | |||
589 | failed: | ||
590 | if (fd >= 0) | ||
591 | close(fd); | ||
592 | if (sock >= 0) | ||
593 | close(sock); | ||
594 | debug("%s: failed to set %s mode %d: %s", __func__, name, | ||
595 | mode, strerror(errno)); | ||
563 | return (-1); | 596 | return (-1); |
564 | } | 597 | } |
565 | 598 | ||