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> |
@@ -606,6 +607,8 @@ percent_expand(const char *string, ...) | |||
606 | /* %% case */ | 607 | /* %% case */ |
607 | if (*string == '%') | 608 | if (*string == '%') |
608 | goto append; | 609 | goto append; |
610 | if (*string == '\0') | ||
611 | fatal("%s: invalid format", __func__); | ||
609 | for (j = 0; j < num_keys; j++) { | 612 | for (j = 0; j < num_keys; j++) { |
610 | if (strchr(keys[j].key, *string) != NULL) { | 613 | if (strchr(keys[j].key, *string) != NULL) { |
611 | i = strlcat(buf, keys[j].repl, sizeof(buf)); | 614 | i = strlcat(buf, keys[j].repl, sizeof(buf)); |
@@ -720,62 +723,63 @@ tun_open(int tun, int mode) | |||
720 | struct ifreq ifr; | 723 | struct ifreq ifr; |
721 | char name[100]; | 724 | char name[100]; |
722 | int fd = -1, sock; | 725 | int fd = -1, sock; |
726 | const char *tunbase = "tun"; | ||
727 | |||
728 | if (mode == SSH_TUNMODE_ETHERNET) | ||
729 | tunbase = "tap"; | ||
723 | 730 | ||
724 | /* Open the tunnel device */ | 731 | /* Open the tunnel device */ |
725 | if (tun <= SSH_TUNID_MAX) { | 732 | if (tun <= SSH_TUNID_MAX) { |
726 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | 733 | snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); |
727 | fd = open(name, O_RDWR); | 734 | fd = open(name, O_RDWR); |
728 | } else if (tun == SSH_TUNID_ANY) { | 735 | } else if (tun == SSH_TUNID_ANY) { |
729 | for (tun = 100; tun >= 0; tun--) { | 736 | for (tun = 100; tun >= 0; tun--) { |
730 | snprintf(name, sizeof(name), "/dev/tun%d", tun); | 737 | snprintf(name, sizeof(name), "/dev/%s%d", |
738 | tunbase, tun); | ||
731 | if ((fd = open(name, O_RDWR)) >= 0) | 739 | if ((fd = open(name, O_RDWR)) >= 0) |
732 | break; | 740 | break; |
733 | } | 741 | } |
734 | } else { | 742 | } else { |
735 | debug("%s: invalid tunnel %u", __func__, tun); | 743 | debug("%s: invalid tunnel %u", __func__, tun); |
736 | return (-1); | 744 | return -1; |
737 | } | 745 | } |
738 | 746 | ||
739 | if (fd < 0) { | 747 | if (fd < 0) { |
740 | debug("%s: %s open failed: %s", __func__, name, strerror(errno)); | 748 | debug("%s: %s open: %s", __func__, name, strerror(errno)); |
741 | return (-1); | 749 | return -1; |
742 | } | 750 | } |
743 | 751 | ||
744 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); | 752 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); |
745 | 753 | ||
746 | /* Set the tunnel device operation mode */ | 754 | /* Bring interface up if it is not already */ |
747 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); | 755 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); |
748 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) | 756 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) |
749 | goto failed; | 757 | goto failed; |
750 | 758 | ||
751 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) | 759 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { |
752 | goto failed; | 760 | debug("%s: get interface %s flags: %s", __func__, |
753 | 761 | ifr.ifr_name, strerror(errno)); | |
754 | /* Set interface mode */ | ||
755 | ifr.ifr_flags &= ~IFF_UP; | ||
756 | if (mode == SSH_TUNMODE_ETHERNET) | ||
757 | ifr.ifr_flags |= IFF_LINK0; | ||
758 | else | ||
759 | ifr.ifr_flags &= ~IFF_LINK0; | ||
760 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | ||
761 | goto failed; | 762 | goto failed; |
763 | } | ||
762 | 764 | ||
763 | /* Bring interface up */ | 765 | if (!(ifr.ifr_flags & IFF_UP)) { |
764 | ifr.ifr_flags |= IFF_UP; | 766 | ifr.ifr_flags |= IFF_UP; |
765 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | 767 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { |
766 | goto failed; | 768 | debug("%s: activate interface %s: %s", __func__, |
769 | ifr.ifr_name, strerror(errno)); | ||
770 | goto failed; | ||
771 | } | ||
772 | } | ||
767 | 773 | ||
768 | close(sock); | 774 | close(sock); |
769 | return (fd); | 775 | return fd; |
770 | 776 | ||
771 | failed: | 777 | failed: |
772 | if (fd >= 0) | 778 | if (fd >= 0) |
773 | close(fd); | 779 | close(fd); |
774 | if (sock >= 0) | 780 | if (sock >= 0) |
775 | close(sock); | 781 | close(sock); |
776 | debug("%s: failed to set %s mode %d: %s", __func__, name, | 782 | return -1; |
777 | mode, strerror(errno)); | ||
778 | return (-1); | ||
779 | #else | 783 | #else |
780 | error("Tunnel interfaces are not supported on this platform"); | 784 | error("Tunnel interfaces are not supported on this platform"); |
781 | return (-1); | 785 | return (-1); |
@@ -1174,7 +1178,7 @@ unix_listener(const char *path, int backlog, int unlink_first) | |||
1174 | void | 1178 | void |
1175 | sock_set_v6only(int s) | 1179 | sock_set_v6only(int s) |
1176 | { | 1180 | { |
1177 | #ifdef IPV6_V6ONLY | 1181 | #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) |
1178 | int on = 1; | 1182 | int on = 1; |
1179 | 1183 | ||
1180 | debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); | 1184 | debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); |