summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--misc.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/misc.c b/misc.c
index ddd2b2db4..b6503abbb 100644
--- a/misc.c
+++ b/misc.c
@@ -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.98 2015/10/07 00:54:06 djm 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.
@@ -666,49 +666,60 @@ tun_open(int tun, int mode)
666 } 666 }
667 } else { 667 } else {
668 debug("%s: invalid tunnel %u", __func__, tun); 668 debug("%s: invalid tunnel %u", __func__, tun);
669 return (-1); 669 return -1;
670 } 670 }
671 671
672 if (fd < 0) { 672 if (fd < 0) {
673 debug("%s: %s open failed: %s", __func__, name, strerror(errno)); 673 debug("%s: %s open: %s", __func__, name, strerror(errno));
674 return (-1); 674 return -1;
675 } 675 }
676 676
677 debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 677 debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
678 678
679 /* Set the tunnel device operation mode */ 679 /* Set the tunnel device operation mode */
680 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); 680 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
681 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 681 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
682 error("%s: socket: %s", __func__, strerror(errno));
682 goto failed; 683 goto failed;
684 }
683 685
684 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) 686 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
687 debug("%s: get interface %s flags: %s", __func__,
688 ifr.ifr_name, strerror(errno));
685 goto failed; 689 goto failed;
690 }
686 691
687 /* Set interface mode */ 692 /* Set interface mode if not already in correct mode */
688 ifr.ifr_flags &= ~IFF_UP; 693 if ((mode == SSH_TUNMODE_ETHERNET && !(ifr.ifr_flags & IFF_LINK0)) ||
689 if (mode == SSH_TUNMODE_ETHERNET) 694 (mode != SSH_TUNMODE_ETHERNET && (ifr.ifr_flags & IFF_LINK0))) {
690 ifr.ifr_flags |= IFF_LINK0; 695 ifr.ifr_flags &= ~IFF_UP;
691 else 696 ifr.ifr_flags ^= IFF_LINK0;
692 ifr.ifr_flags &= ~IFF_LINK0; 697 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
693 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 698 debug("%s: reset interface %s flags: %s", __func__,
694 goto failed; 699 ifr.ifr_name, strerror(errno));
700 goto failed;
701 }
702 }
695 703
696 /* Bring interface up */ 704 /* Bring interface up if it is not already */
697 ifr.ifr_flags |= IFF_UP; 705 if (!(ifr.ifr_flags & IFF_UP)) {
698 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 706 ifr.ifr_flags |= IFF_UP;
699 goto failed; 707 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
708 debug("%s: activate interface %s: %s", __func__,
709 ifr.ifr_name, strerror(errno));
710 goto failed;
711 }
712 }
700 713
701 close(sock); 714 close(sock);
702 return (fd); 715 return fd;
703 716
704 failed: 717 failed:
705 if (fd >= 0) 718 if (fd >= 0)
706 close(fd); 719 close(fd);
707 if (sock >= 0) 720 if (sock >= 0)
708 close(sock); 721 close(sock);
709 debug("%s: failed to set %s mode %d: %s", __func__, name, 722 return -1;
710 mode, strerror(errno));
711 return (-1);
712#else 723#else
713 error("Tunnel interfaces are not supported on this platform"); 724 error("Tunnel interfaces are not supported on this platform");
714 return (-1); 725 return (-1);