diff --git a/gns3server/modules/base_manager.py b/gns3server/modules/base_manager.py index 9b3cc6da..3ee0b347 100644 --- a/gns3server/modules/base_manager.py +++ b/gns3server/modules/base_manager.py @@ -28,6 +28,7 @@ import logging log = logging.getLogger(__name__) from uuid import UUID, uuid4 +from gns3server.utils.interfaces import is_interface_up from ..config import Config from ..utils.asyncio import wait_run_in_executor from .project_manager import ProjectManager @@ -369,12 +370,17 @@ class BaseManager: nio = NIOUDP(lport, rhost, rport) elif nio_settings["type"] == "nio_tap": tap_device = nio_settings["tap_device"] + if not is_interface_up(tap_device): + raise aiohttp.web.HTTPConflict(text="TAP interface {} is down".format(tap_device)) # FIXME: check for permissions on tap device # if not self._has_privileged_access(executable): # raise aiohttp.web.HTTPForbidden(text="{} has no privileged access to {}.".format(executable, tap_device)) nio = NIOTAP(tap_device) elif nio_settings["type"] == "nio_generic_ethernet": - nio = NIOGenericEthernet(nio_settings["ethernet_device"]) + ethernet_device = nio_settings["ethernet_device"] + if not is_interface_up(ethernet_device): + raise aiohttp.web.HTTPConflict(text="Ethernet interface {} is down".format(ethernet_device)) + nio = NIOGenericEthernet(ethernet_device) elif nio_settings["type"] == "nio_nat": nio = NIONAT() assert nio is not None diff --git a/gns3server/modules/dynamips/__init__.py b/gns3server/modules/dynamips/__init__.py index b4910585..d68bf5f5 100644 --- a/gns3server/modules/dynamips/__init__.py +++ b/gns3server/modules/dynamips/__init__.py @@ -32,7 +32,7 @@ import logging log = logging.getLogger(__name__) -from gns3server.utils.interfaces import get_windows_interfaces +from gns3server.utils.interfaces import get_windows_interfaces, is_interface_up from gns3server.utils.asyncio import wait_run_in_executor from pkg_resources import parse_version from uuid import UUID, uuid4 @@ -404,6 +404,8 @@ class Dynamips(BaseManager): raise DynamipsError("Could not find interface {} on this host".format(ethernet_device)) else: ethernet_device = npf_interface + if not is_interface_up(ethernet_device): + raise aiohttp.web.HTTPConflict(text="Ethernet interface {} is down".format(ethernet_device)) nio = NIOGenericEthernet(node.hypervisor, ethernet_device) elif nio_settings["type"] == "nio_linux_ethernet": if sys.platform.startswith("win"): @@ -412,6 +414,8 @@ class Dynamips(BaseManager): nio = NIOLinuxEthernet(node.hypervisor, ethernet_device) elif nio_settings["type"] == "nio_tap": tap_device = nio_settings["tap_device"] + if not is_interface_up(tap_device): + raise aiohttp.web.HTTPConflict(text="TAP interface {} is down".format(tap_device)) nio = NIOTAP(node.hypervisor, tap_device) elif nio_settings["type"] == "nio_unix": local_file = nio_settings["local_file"] diff --git a/gns3server/utils/interfaces.py b/gns3server/utils/interfaces.py index c9a5df88..60c16c61 100644 --- a/gns3server/utils/interfaces.py +++ b/gns3server/utils/interfaces.py @@ -18,6 +18,8 @@ import sys import aiohttp +import socket +import struct import logging log = logging.getLogger(__name__) @@ -78,6 +80,31 @@ def get_windows_interfaces(): return interfaces +def is_interface_up(interface): + """ + Checks if an interface is up. + + :param interface: interface name + + :returns: boolean + """ + + if sys.platform.startswith("linux"): + import fcntl + SIOCGIFFLAGS = 0x8913 + try: + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + result = fcntl.ioctl(s.fileno(), SIOCGIFFLAGS, interface + '\0' * 256) + flags, = struct.unpack('H', result[16:18]) + if flags & 1: # check if the up bit is set + return True + return False + except OSError as e: + raise aiohttp.web.HTTPInternalServerError(text="Exception when checking if {} is up: {}".format(interface, e)) + else: + #TODO: Windows & OSX support + return True + def interfaces(): """ Gets the network interfaces on this server.