diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 58 |
1 files changed, 31 insertions, 27 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.97 2015/04/24 01:36:00 deraadt Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.101 2016/01/20 09:22:39 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -29,6 +29,7 @@ | |||
29 | #include <sys/types.h> | 29 | #include <sys/types.h> |
30 | #include <sys/ioctl.h> | 30 | #include <sys/ioctl.h> |
31 | #include <sys/socket.h> | 31 | #include <sys/socket.h> |
32 | #include <sys/time.h> | ||
32 | #include <sys/un.h> | 33 | #include <sys/un.h> |
33 | 34 | ||
34 | #include <limits.h> | 35 | #include <limits.h> |
@@ -604,6 +605,8 @@ percent_expand(const char *string, ...) | |||
604 | /* %% case */ | 605 | /* %% case */ |
605 | if (*string == '%') | 606 | if (*string == '%') |
606 | goto append; | 607 | goto append; |
608 | if (*string == '\0') | ||
609 | fatal("%s: invalid format", __func__); | ||
607 | for (j = 0; j < num_keys; j++) { | 610 | for (j = 0; j < num_keys; j++) { |
608 | if (strchr(keys[j].key, *string) != NULL) { | 611 | if (strchr(keys[j].key, *string) != NULL) { |
609 | i = strlcat(buf, keys[j].repl, sizeof(buf)); | 612 | i = strlcat(buf, keys[j].repl, sizeof(buf)); |
@@ -653,62 +656,63 @@ tun_open(int tun, int mode) | |||
653 | struct ifreq ifr; | 656 | struct ifreq ifr; |
654 | char name[100]; | 657 | char name[100]; |
655 | int fd = -1, sock; | 658 | int fd = -1, sock; |
659 | const char *tunbase = "tun"; | ||
660 | |||
661 | if (mode == SSH_TUNMODE_ETHERNET) | ||
662 | tunbase = "tap"; | ||
656 | 663 | ||
657 | /* Open the tunnel device */ | 664 | /* Open the tunnel device */ |
658 | if (tun <= SSH_TUNID_MAX) { | 665 | if (tun <= SSH_TUNID_MAX) { |
659 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | 666 | snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); |
660 | fd = open(name, O_RDWR); | 667 | fd = open(name, O_RDWR); |
661 | } else if (tun == SSH_TUNID_ANY) { | 668 | } else if (tun == SSH_TUNID_ANY) { |
662 | for (tun = 100; tun >= 0; tun--) { | 669 | for (tun = 100; tun >= 0; tun--) { |
663 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | 670 | snprintf(name, sizeof(name), "/dev/%s%d", |
671 | tunbase, tun); | ||
664 | if ((fd = open(name, O_RDWR)) >= 0) | 672 | if ((fd = open(name, O_RDWR)) >= 0) |
665 | break; | 673 | break; |
666 | } | 674 | } |
667 | } else { | 675 | } else { |
668 | debug("%s: invalid tunnel %u", __func__, tun); | 676 | debug("%s: invalid tunnel %u", __func__, tun); |
669 | return (-1); | 677 | return -1; |
670 | } | 678 | } |
671 | 679 | ||
672 | if (fd < 0) { | 680 | if (fd < 0) { |
673 | debug("%s: %s open failed: %s", __func__, name, strerror(errno)); | 681 | debug("%s: %s open: %s", __func__, name, strerror(errno)); |
674 | return (-1); | 682 | return -1; |
675 | } | 683 | } |
676 | 684 | ||
677 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); | 685 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); |
678 | 686 | ||
679 | /* Set the tunnel device operation mode */ | 687 | /* Bring interface up if it is not already */ |
680 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); | 688 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); |
681 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) | 689 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) |
682 | goto failed; | 690 | goto failed; |
683 | 691 | ||
684 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) | 692 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { |
685 | goto failed; | 693 | debug("%s: get interface %s flags: %s", __func__, |
686 | 694 | ifr.ifr_name, strerror(errno)); | |
687 | /* Set interface mode */ | ||
688 | ifr.ifr_flags &= ~IFF_UP; | ||
689 | if (mode == SSH_TUNMODE_ETHERNET) | ||
690 | ifr.ifr_flags |= IFF_LINK0; | ||
691 | else | ||
692 | ifr.ifr_flags &= ~IFF_LINK0; | ||
693 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | ||
694 | goto failed; | 695 | goto failed; |
696 | } | ||
695 | 697 | ||
696 | /* Bring interface up */ | 698 | if (!(ifr.ifr_flags & IFF_UP)) { |
697 | ifr.ifr_flags |= IFF_UP; | 699 | ifr.ifr_flags |= IFF_UP; |
698 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | 700 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { |
699 | goto failed; | 701 | debug("%s: activate interface %s: %s", __func__, |
702 | ifr.ifr_name, strerror(errno)); | ||
703 | goto failed; | ||
704 | } | ||
705 | } | ||
700 | 706 | ||
701 | close(sock); | 707 | close(sock); |
702 | return (fd); | 708 | return fd; |
703 | 709 | ||
704 | failed: | 710 | failed: |
705 | if (fd >= 0) | 711 | if (fd >= 0) |
706 | close(fd); | 712 | close(fd); |
707 | if (sock >= 0) | 713 | if (sock >= 0) |
708 | close(sock); | 714 | close(sock); |
709 | debug("%s: failed to set %s mode %d: %s", __func__, name, | 715 | return -1; |
710 | mode, strerror(errno)); | ||
711 | return (-1); | ||
712 | #else | 716 | #else |
713 | error("Tunnel interfaces are not supported on this platform"); | 717 | error("Tunnel interfaces are not supported on this platform"); |
714 | return (-1); | 718 | return (-1); |
@@ -1107,7 +1111,7 @@ unix_listener(const char *path, int backlog, int unlink_first) | |||
1107 | void | 1111 | void |
1108 | sock_set_v6only(int s) | 1112 | sock_set_v6only(int s) |
1109 | { | 1113 | { |
1110 | #ifdef IPV6_V6ONLY | 1114 | #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) |
1111 | int on = 1; | 1115 | int on = 1; |
1112 | 1116 | ||
1113 | debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); | 1117 | debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); |