diff --git a/analyzer/python/ikos/http.py b/analyzer/python/ikos/http.py index 3b7d6117..59b334c3 100644 --- a/analyzer/python/ikos/http.py +++ b/analyzer/python/ikos/http.py @@ -50,3 +50,36 @@ from urlparse import parse_qs from urllib import urlencode from urllib2 import urlopen + +from errno import EAFNOSUPPORT +from socket import AF_INET, AF_INET6 +import os + +class HTTPServerIPv6(HTTPServer): + ''' + HTTP server that listens on IPv6 when available. + + In systems with dual stack, this also listens on IPv4. + + This class tries to listen on IPv6 first (and IPv4 if available). If that + is not supported, then it tries IPv4 only. + ''' + + address_family = AF_INET6 + + def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): + try: + # Initially try to open the server with IPv6. This will also select + # IPv4 on systems with dual stack. + super().__init__(server_address, RequestHandlerClass, bind_and_activate) + + except OSError as e: + if e.errno == EAFNOSUPPORT: + # If the exception is due to IPv6 not being supported, we + # select IPv4 only and try to re-open the server again. + self.address_family = AF_INET + super().__init__(server_address, RequestHandlerClass, bind_and_activate) + else: + # If the exception is for any other reason other than IPv6 not + # being supported, then we cannot do anything about it. + raise e diff --git a/analyzer/python/ikos/scan.py b/analyzer/python/ikos/scan.py index 188c14a2..e5bbfc84 100644 --- a/analyzer/python/ikos/scan.py +++ b/analyzer/python/ikos/scan.py @@ -641,8 +641,8 @@ def __init__(self): try: # try to start the http server on a random port self.port = random.randint(8000, 9000) - self.httpd = http.HTTPServer(('', self.port), - ScanServerRequestHandler) + self.httpd = http.HTTPServerIPv6(('', self.port), + ScanServerRequestHandler) except (OSError, IOError): self.port = None # port already in use diff --git a/analyzer/python/ikos/view.py b/analyzer/python/ikos/view.py index f8aeb508..9710bf47 100644 --- a/analyzer/python/ikos/view.py +++ b/analyzer/python/ikos/view.py @@ -62,7 +62,7 @@ from ikos import settings from ikos.enums import Result, CheckKind from ikos.highlight import CppLexer, HtmlFormatter, highlight -from ikos.http import HTTPServer, BaseHTTPRequestHandler +from ikos.http import HTTPServerIPv6, BaseHTTPRequestHandler from ikos.log import printf from ikos.output_db import OutputDatabase @@ -337,7 +337,7 @@ def __init__(self, db, port=8080): self.report = ViewReport(self.db) try: - self.httpd = HTTPServer(('', self.port), RequestHandler) + self.httpd = HTTPServerIPv6(('', self.port), RequestHandler) except (OSError, IOError) as e: log.error("Could not start the HTTP server: %s" % e) sys.exit(1)