diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 173 |
1 files changed, 169 insertions, 4 deletions
@@ -24,7 +24,11 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | RCSID("$OpenBSD: misc.c,v 1.34 2005/07/08 09:26:18 dtucker Exp $"); | 27 | RCSID("$OpenBSD: misc.c,v 1.42 2006/01/31 10:19:02 djm Exp $"); |
28 | |||
29 | #ifdef SSH_TUN_OPENBSD | ||
30 | #include <net/if.h> | ||
31 | #endif | ||
28 | 32 | ||
29 | #include "misc.h" | 33 | #include "misc.h" |
30 | #include "log.h" | 34 | #include "log.h" |
@@ -194,6 +198,37 @@ a2port(const char *s) | |||
194 | return port; | 198 | return port; |
195 | } | 199 | } |
196 | 200 | ||
201 | int | ||
202 | a2tun(const char *s, int *remote) | ||
203 | { | ||
204 | const char *errstr = NULL; | ||
205 | char *sp, *ep; | ||
206 | int tun; | ||
207 | |||
208 | if (remote != NULL) { | ||
209 | *remote = SSH_TUNID_ANY; | ||
210 | sp = xstrdup(s); | ||
211 | if ((ep = strchr(sp, ':')) == NULL) { | ||
212 | xfree(sp); | ||
213 | return (a2tun(s, NULL)); | ||
214 | } | ||
215 | ep[0] = '\0'; ep++; | ||
216 | *remote = a2tun(ep, NULL); | ||
217 | tun = a2tun(sp, NULL); | ||
218 | xfree(sp); | ||
219 | return (*remote == SSH_TUNID_ERR ? *remote : tun); | ||
220 | } | ||
221 | |||
222 | if (strcasecmp(s, "any") == 0) | ||
223 | return (SSH_TUNID_ANY); | ||
224 | |||
225 | tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); | ||
226 | if (errstr != NULL) | ||
227 | return (SSH_TUNID_ERR); | ||
228 | |||
229 | return (tun); | ||
230 | } | ||
231 | |||
197 | #define SECONDS 1 | 232 | #define SECONDS 1 |
198 | #define MINUTES (SECONDS * 60) | 233 | #define MINUTES (SECONDS * 60) |
199 | #define HOURS (MINUTES * 60) | 234 | #define HOURS (MINUTES * 60) |
@@ -356,12 +391,15 @@ void | |||
356 | addargs(arglist *args, char *fmt, ...) | 391 | addargs(arglist *args, char *fmt, ...) |
357 | { | 392 | { |
358 | va_list ap; | 393 | va_list ap; |
359 | char buf[1024]; | 394 | char *cp; |
360 | u_int nalloc; | 395 | u_int nalloc; |
396 | int r; | ||
361 | 397 | ||
362 | va_start(ap, fmt); | 398 | va_start(ap, fmt); |
363 | vsnprintf(buf, sizeof(buf), fmt, ap); | 399 | r = vasprintf(&cp, fmt, ap); |
364 | va_end(ap); | 400 | va_end(ap); |
401 | if (r == -1) | ||
402 | fatal("addargs: argument too long"); | ||
365 | 403 | ||
366 | nalloc = args->nalloc; | 404 | nalloc = args->nalloc; |
367 | if (args->list == NULL) { | 405 | if (args->list == NULL) { |
@@ -372,10 +410,44 @@ addargs(arglist *args, char *fmt, ...) | |||
372 | 410 | ||
373 | args->list = xrealloc(args->list, nalloc * sizeof(char *)); | 411 | args->list = xrealloc(args->list, nalloc * sizeof(char *)); |
374 | args->nalloc = nalloc; | 412 | args->nalloc = nalloc; |
375 | args->list[args->num++] = xstrdup(buf); | 413 | args->list[args->num++] = cp; |
376 | args->list[args->num] = NULL; | 414 | args->list[args->num] = NULL; |
377 | } | 415 | } |
378 | 416 | ||
417 | void | ||
418 | replacearg(arglist *args, u_int which, char *fmt, ...) | ||
419 | { | ||
420 | va_list ap; | ||
421 | char *cp; | ||
422 | int r; | ||
423 | |||
424 | va_start(ap, fmt); | ||
425 | r = vasprintf(&cp, fmt, ap); | ||
426 | va_end(ap); | ||
427 | if (r == -1) | ||
428 | fatal("replacearg: argument too long"); | ||
429 | |||
430 | if (which >= args->num) | ||
431 | fatal("replacearg: tried to replace invalid arg %d >= %d", | ||
432 | which, args->num); | ||
433 | xfree(args->list[which]); | ||
434 | args->list[which] = cp; | ||
435 | } | ||
436 | |||
437 | void | ||
438 | freeargs(arglist *args) | ||
439 | { | ||
440 | u_int i; | ||
441 | |||
442 | if (args->list != NULL) { | ||
443 | for (i = 0; i < args->num; i++) | ||
444 | xfree(args->list[i]); | ||
445 | xfree(args->list); | ||
446 | args->nalloc = args->num = 0; | ||
447 | args->list = NULL; | ||
448 | } | ||
449 | } | ||
450 | |||
379 | /* | 451 | /* |
380 | * Expands tildes in the file name. Returns data allocated by xmalloc. | 452 | * Expands tildes in the file name. Returns data allocated by xmalloc. |
381 | * Warning: this calls getpw*. | 453 | * Warning: this calls getpw*. |
@@ -507,6 +579,99 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, | |||
507 | return -1; | 579 | return -1; |
508 | } | 580 | } |
509 | 581 | ||
582 | int | ||
583 | tun_open(int tun, int mode) | ||
584 | { | ||
585 | #if defined(CUSTOM_SYS_TUN_OPEN) | ||
586 | return (sys_tun_open(tun, mode)); | ||
587 | #elif defined(SSH_TUN_OPENBSD) | ||
588 | struct ifreq ifr; | ||
589 | char name[100]; | ||
590 | int fd = -1, sock; | ||
591 | |||
592 | /* Open the tunnel device */ | ||
593 | if (tun <= SSH_TUNID_MAX) { | ||
594 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | ||
595 | fd = open(name, O_RDWR); | ||
596 | } else if (tun == SSH_TUNID_ANY) { | ||
597 | for (tun = 100; tun >= 0; tun--) { | ||
598 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | ||
599 | if ((fd = open(name, O_RDWR)) >= 0) | ||
600 | break; | ||
601 | } | ||
602 | } else { | ||
603 | debug("%s: invalid tunnel %u", __func__, tun); | ||
604 | return (-1); | ||
605 | } | ||
606 | |||
607 | if (fd < 0) { | ||
608 | debug("%s: %s open failed: %s", __func__, name, strerror(errno)); | ||
609 | return (-1); | ||
610 | } | ||
611 | |||
612 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); | ||
613 | |||
614 | /* Set the tunnel device operation mode */ | ||
615 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); | ||
616 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) | ||
617 | goto failed; | ||
618 | |||
619 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) | ||
620 | goto failed; | ||
621 | |||
622 | /* Set interface mode */ | ||
623 | ifr.ifr_flags &= ~IFF_UP; | ||
624 | if (mode == SSH_TUNMODE_ETHERNET) | ||
625 | ifr.ifr_flags |= IFF_LINK0; | ||
626 | else | ||
627 | ifr.ifr_flags &= ~IFF_LINK0; | ||
628 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | ||
629 | goto failed; | ||
630 | |||
631 | /* Bring interface up */ | ||
632 | ifr.ifr_flags |= IFF_UP; | ||
633 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | ||
634 | goto failed; | ||
635 | |||
636 | close(sock); | ||
637 | return (fd); | ||
638 | |||
639 | failed: | ||
640 | if (fd >= 0) | ||
641 | close(fd); | ||
642 | if (sock >= 0) | ||
643 | close(sock); | ||
644 | debug("%s: failed to set %s mode %d: %s", __func__, name, | ||
645 | mode, strerror(errno)); | ||
646 | return (-1); | ||
647 | #else | ||
648 | error("Tunnel interfaces are not supported on this platform"); | ||
649 | return (-1); | ||
650 | #endif | ||
651 | } | ||
652 | |||
653 | void | ||
654 | sanitise_stdfd(void) | ||
655 | { | ||
656 | int nullfd, dupfd; | ||
657 | |||
658 | if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { | ||
659 | fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno)); | ||
660 | exit(1); | ||
661 | } | ||
662 | while (++dupfd <= 2) { | ||
663 | /* Only clobber closed fds */ | ||
664 | if (fcntl(dupfd, F_GETFL, 0) >= 0) | ||
665 | continue; | ||
666 | if (dup2(nullfd, dupfd) == -1) { | ||
667 | fprintf(stderr, "dup2: %s", strerror(errno)); | ||
668 | exit(1); | ||
669 | } | ||
670 | } | ||
671 | if (nullfd > 2) | ||
672 | close(nullfd); | ||
673 | } | ||
674 | |||
510 | char * | 675 | char * |
511 | tohex(const u_char *d, u_int l) | 676 | tohex(const u_char *d, u_int l) |
512 | { | 677 | { |