From fdc9283e041be83cfd8fcf621ba1e04c4a179ae3 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sun, 13 Nov 2016 20:28:14 +1100 Subject: [PATCH] Generic code the bind an Ethernet interface with uBridge. Ref #771. --- gns3server/compute/base_node.py | 45 +++++++++++++++++++++++++- gns3server/compute/vmware/vmware_vm.py | 30 ++--------------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py index 27e0c56f..f83e3158 100644 --- a/gns3server/compute/base_node.py +++ b/gns3server/compute/base_node.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import sys import os import stat import logging @@ -25,6 +26,7 @@ import tempfile import psutil import platform +from gns3server.utils.interfaces import interfaces from ..compute.port_manager import PortManager from ..utils.asyncio import wait_run_in_executor from ..utils.asyncio.telnet_server import AsyncioTelnetServer @@ -543,7 +545,7 @@ class BaseNode: @asyncio.coroutine def _add_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): """ - Creates a connection in uBridge. + Creates an UDP connection in uBridge. :param bridge_name: bridge name in uBridge :param source_nio: source NIO instance @@ -571,6 +573,47 @@ class BaseNode: yield from self._ubridge_send('bridge start {name}'.format(name=bridge_name)) + @asyncio.coroutine + def _add_ubridge_ethernet_connection(self, bridge_name, ethernet_interface, block_host_traffic=True): + """ + Creates a connection with an Ethernet interface in uBridge. + + :param bridge_name: bridge name in uBridge + :param ethernet_interface: Ethernet interface name + :param block_host_traffic: block network traffic originating from the host OS (Windows only) + """ + + if sys.platform.startswith("linux"): + # on Linux we use RAW sockets + yield from self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=bridge_name, interface=ethernet_interface)) + elif sys.platform.startswith("win"): + # on Windows we use Winpcap/Npcap + windows_interfaces = interfaces() + npf_id = None + source_mac = None + for interface in windows_interfaces: + # Winpcap/Npcap uses a NPF ID to identify an interface on Windows + if "netcard" in interface and ethernet_interface in interface["netcard"]: + npf_id = interface["id"] + source_mac = interface["mac_address"] + elif ethernet_interface in interface["name"]: + npf_id = interface["id"] + source_mac = interface["mac_address"] + if npf_id: + yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, + interface=npf_id)) + else: + raise NodeError("Could not find NPF id for VMnet interface {}".format(ethernet_interface)) + + if block_host_traffic: + if source_mac: + yield from self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=bridge_name, mac=source_mac)) + else: + log.warn("Could not block host network traffic on {} (no MAC address found)".format(ethernet_interface)) + else: + # on other platforms we just rely on the pcap library + yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=ethernet_interface)) + def _create_local_udp_tunnel(self): """ Creates a local UDP tunnel (pair of 2 NIOs, one for each direction) diff --git a/gns3server/compute/vmware/vmware_vm.py b/gns3server/compute/vmware/vmware_vm.py index d2892b22..de3c7333 100644 --- a/gns3server/compute/vmware/vmware_vm.py +++ b/gns3server/compute/vmware/vmware_vm.py @@ -21,7 +21,6 @@ VMware VM instance. import sys import os -import socket import asyncio import tempfile @@ -298,35 +297,12 @@ class VMwareVM(BaseNode): raise VMwareError("vnet {} not in VMX file".format(vnet)) yield from self._ubridge_send("bridge create {name}".format(name=vnet)) vmnet_interface = os.path.basename(self._vmx_pairs[vnet]) - if sys.platform.startswith("linux"): - yield from self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=vnet, interface=vmnet_interface)) - elif sys.platform.startswith("win"): - windows_interfaces = interfaces() - npf = None - source_mac = None - for interface in windows_interfaces: - if "netcard" in interface and vmnet_interface in interface["netcard"]: - npf = interface["id"] - source_mac = interface["mac_address"] - elif vmnet_interface in interface["name"]: - npf = interface["id"] - source_mac = interface["mac_address"] - if npf: - yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet, interface=npf)) - else: - raise VMwareError("Could not find NPF id for VMnet interface {}".format(vmnet_interface)) - if block_host_traffic: - if source_mac: - yield from self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet, mac=source_mac)) - else: - log.warn("Could not block host network traffic on {} (no MAC address found)".format(vmnet_interface)) - - elif sys.platform.startswith("darwin"): + if sys.platform.startswith("darwin"): + # special case on OSX, we cannot bind VMnet interfaces using the libpcap yield from self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet, interface=vmnet_interface)) else: - yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet, - interface=vmnet_interface)) + yield from self._add_ubridge_ethernet_connection(vnet, vmnet_interface, block_host_traffic) if isinstance(nio, NIOUDP): yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=vnet,