diff --git a/gns3server/modules/base_manager.py b/gns3server/modules/base_manager.py index 674eb419..9b3cc6da 100644 --- a/gns3server/modules/base_manager.py +++ b/gns3server/modules/base_manager.py @@ -357,9 +357,13 @@ class BaseManager: rhost = nio_settings["rhost"] rport = nio_settings["rport"] try: - # TODO: handle IPv6 - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: - sock.connect((rhost, rport)) + info = socket.getaddrinfo(rhost, rport, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE) + if not info: + raise aiohttp.web.HTTPInternalServerError(text="getaddrinfo returns an empty list on {}:{}".format(rhost, rport)) + for res in info: + af, socktype, proto, _, sa = res + with socket.socket(af, socktype, proto) as sock: + sock.connect(sa) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e)) nio = NIOUDP(lport, rhost, rport) diff --git a/gns3server/modules/dynamips/__init__.py b/gns3server/modules/dynamips/__init__.py index 2f9492a1..f0658891 100644 --- a/gns3server/modules/dynamips/__init__.py +++ b/gns3server/modules/dynamips/__init__.py @@ -331,10 +331,16 @@ class Dynamips(BaseManager): server_host = server_config.get("host") try: - # let the OS find an unused port for the Dynamips hypervisor - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: - sock.bind((server_host, 0)) - port = sock.getsockname()[1] + info = socket.getaddrinfo(server_host, 0, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) + if not info: + raise DynamipsError("getaddrinfo returns an empty list on {}".format(server_host)) + for res in info: + af, socktype, proto, _, sa = res + # let the OS find an unused port for the Dynamips hypervisor + with socket.socket(af, socktype, proto) as sock: + sock.bind(sa) + port = sock.getsockname()[1] + break except OSError as e: raise DynamipsError("Could not find free port for the Dynamips hypervisor: {}".format(e)) @@ -375,9 +381,13 @@ class Dynamips(BaseManager): rhost = nio_settings["rhost"] rport = nio_settings["rport"] try: - # TODO: handle IPv6 - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: - sock.connect((rhost, rport)) + info = socket.getaddrinfo(rhost, rport, 0, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE) + if not info: + raise DynamipsError("getaddrinfo returns an empty list on {}:{}".format(rhost, rport)) + for res in info: + af, socktype, proto, _, sa = res + with socket.socket(af, socktype, proto) as sock: + sock.connect(sa) except OSError as e: raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e)) nio = NIOUDP(node.hypervisor, lport, rhost, rport) diff --git a/gns3server/modules/iou/ioucon.py b/gns3server/modules/iou/ioucon.py index 47c542ed..6f470843 100644 --- a/gns3server/modules/iou/ioucon.py +++ b/gns3server/modules/iou/ioucon.py @@ -355,13 +355,19 @@ class TelnetServer(Console): def __enter__(self): # Open a socket and start listening - sock_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - try: - sock_fd.bind((self.addr, self.port)) - except OSError: - raise TelnetServerError("Cannot bind to {}:{}" - .format(self.addr, self.port)) + + info = socket.getaddrinfo(self.addr, self.port, 0, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) + if not info: + raise TelnetServerError("getaddrinfo returns an empty list on {}:{}".format(self.addr, self.port)) + for res in info: + af, socktype, proto, _, sa = res + sock_fd = socket.socket(af, socktype, proto) + sock_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock_fd.bind(sa) + except OSError: + raise TelnetServerError("Cannot bind to {}:{}" + .format(self.addr, self.port)) sock_fd.listen(socket.SOMAXCONN) self.sock_fd = sock_fd diff --git a/gns3server/modules/port_manager.py b/gns3server/modules/port_manager.py index 0422e4ec..d0d3f7a0 100644 --- a/gns3server/modules/port_manager.py +++ b/gns3server/modules/port_manager.py @@ -151,16 +151,12 @@ class PortManager: if port in ignore_ports: continue try: - if ":" in host: - # IPv6 address support - with socket.socket(socket.AF_INET6, socket_type) as s: + for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket_type, 0, socket.AI_PASSIVE): + af, socktype, proto, _, sa = res + with socket.socket(af, socktype, proto) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind((host, port)) # the port is available if bind is a success - else: - with socket.socket(socket.AF_INET, socket_type) as s: - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind((host, port)) # the port is available if bind is a success - return port + s.bind(sa) # the port is available if bind is a success + return port except OSError as e: last_exception = e if port + 1 == end_port: diff --git a/gns3server/modules/qemu/qemu_vm.py b/gns3server/modules/qemu/qemu_vm.py index 7d0a164d..f51dce34 100644 --- a/gns3server/modules/qemu/qemu_vm.py +++ b/gns3server/modules/qemu/qemu_vm.py @@ -615,10 +615,15 @@ class QemuVM(BaseVM): if self._manager.config.get_section_config("Qemu").getboolean("monitor", True): try: - # let the OS find an unused port for the Qemu monitor - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: - sock.bind((self._monitor_host, 0)) - self._monitor = sock.getsockname()[1] + info = socket.getaddrinfo(self._monitor_host, 0, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) + if not info: + raise QemuError("getaddrinfo returns an empty list on {}".format(self._monitor_host)) + for res in info: + af, socktype, proto, _, sa = res + # let the OS find an unused port for the Qemu monitor + with socket.socket(af, socktype, proto) as sock: + sock.bind(sa) + self._monitor = sock.getsockname()[1] except OSError as e: raise QemuError("Could not find free port for the Qemu monitor: {}".format(e)) diff --git a/gns3server/utils/telnet_server.py b/gns3server/utils/telnet_server.py index a5d3ef4d..9bf7140e 100644 --- a/gns3server/utils/telnet_server.py +++ b/gns3server/utils/telnet_server.py @@ -60,14 +60,13 @@ class TelnetServer(threading.Thread): # we must a thread for reading the pipe on Windows because it is a Named Pipe and it cannot be monitored by select() self._use_thread = True - if ":" in self._host: - # IPv6 address support - self._server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - else: - self._server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): + af, socktype, proto, _, sa = res + self._server_socket = socket.socket(af, socktype, proto) self._server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self._server_socket.bind((self._host, self._port)) + self._server_socket.bind(sa) self._server_socket.listen(socket.SOMAXCONN) + break log.info("Telnet server initialized, waiting for clients on {}:{}".format(self._host, self._port))