From ffe551fdbbade14e1a8de84ac48064aa7b45e2c1 Mon Sep 17 00:00:00 2001 From: antialias Date: Mon, 10 Sep 2012 19:59:30 -0400 Subject: Implemented basic networks checks: valid interface, default route, and can ping the listed gateway. --- pkg/requirements.pip | 1 + src/leap/eip/checks.py | 53 +++++++++++++++++++++++++++++++++++++-- src/leap/eip/exceptions.py | 13 ++++++++++ src/leap/eip/tests/test_checks.py | 26 ++++++++++++++++++- 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/pkg/requirements.pip b/pkg/requirements.pip index 96e76d34..e201906f 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -1,3 +1,4 @@ argparse configuration +ping requests diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 4a2a9599..412be27b 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -1,7 +1,10 @@ import logging import ssl +import platform import os +import netifaces +import ping import requests from leap.base import constants as baseconstants @@ -319,8 +322,54 @@ class EIPConfigChecker(object): # We should WRITE eip config if missing or # incomplete at this point - def ping_gateway(self): - raise NotImplementedError + def test_internet_connection(self): + try: + requests.get('http://216.172.161.165') + except (requests.HTTPError, requests.RequestException) as e: + self.error = e.message + except requests.ConenctionError as e: + if e.message == "[Errno 113] No route to host": + if not self.is_internet_up(): + self.error = "No valid internet connection found." + else: + self.error = "Provider server appears to be down." + + def is_internet_up(self): + iface, gateway = self.get_default_interface_gateway() + self.ping_gateway(self) + + def get_default_interface_gateway(self): + """only impletemented for linux so far.""" + if not platform.system() == "Linux": + raise NotImplementedError + + f = open("/proc/net/route") + route_table = f.readlines() + #toss out header + route_table.pop(0) + + default_iface = None + gateway = None + while route_table: + line = route_table.pop(0) + iface, destination, gateway = line.split('\t')[0:3] + if destination == '00000000': + default_iface = iface + break + + if not default_iface: + raise eipexceptions.NoDefaultInterfaceFoundError + + if default_iface not in netifaces.interfaces(): + raise eipexceptions.InterfaceNotFoundError + + return default_iface, gateway + + def ping_gateway(self, gateway): + #TODO: Discuss how much packet loss (%) is acceptable. + packet_loss = ping.quiet_ping(gateway)[0] + if packet_loss > 10: + raise eipexceptions.NoConnectionToGateway # # private helpers diff --git a/src/leap/eip/exceptions.py b/src/leap/eip/exceptions.py index 3c8f6afb..4d0d70e2 100644 --- a/src/leap/eip/exceptions.py +++ b/src/leap/eip/exceptions.py @@ -108,6 +108,19 @@ class EIPInitBadProviderError(EIPClientError): class EIPConfigurationError(EIPClientError): pass + +class NoDefaultInterfaceFoundError(EIPClientError): + pass + + +class InterfaceNotFoundError(EIPClientError): + pass + + +class NoConnectionToGateway(EIPClientError): + pass + + # # Errors that probably we don't need anymore # chase down for them and check. diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py index 0a87f573..1edcdfb2 100644 --- a/src/leap/eip/tests/test_checks.py +++ b/src/leap/eip/tests/test_checks.py @@ -8,8 +8,10 @@ except ImportError: import os import urlparse -from mock import patch, Mock +from StringIO import StringIO +from mock import patch, Mock, MagicMock +import ping import requests from leap.base import config as baseconfig @@ -23,6 +25,8 @@ from leap.testing.basetest import BaseLeapTest from leap.testing.https_server import BaseHTTPSServerTestCase from leap.testing.https_server import where as where_cert +_uid = os.getuid() + class NoLogRequestHandler: def log_message(self, *args): @@ -170,6 +174,26 @@ class EIPCheckTest(BaseLeapTest): sampleconfig = copy.copy(testdata.EIP_SAMPLE_JSON) checker.check_complete_eip_config(config=sampleconfig) + def test_get_default_interface_no_interface(self): + checker = eipchecks.EIPConfigChecker() + with patch('leap.eip.checks.open', create=True) as mock_open: + with self.assertRaises(eipexceptions.NoDefaultInterfaceFoundError): + mock_open.return_value = \ + StringIO("Iface\tDestination Gateway\tFlags\tRefCntd\tUse\tMetric\tMask\tMTU\tWindow\tIRTT") + checker.get_default_interface_gateway() + + def test_ping_gateway_fail(self): + checker = eipchecks.EIPConfigChecker() + with patch.object(ping, "quiet_ping") as mocked_ping: + with self.assertRaises(eipexceptions.NoConnectionToGateway): + mocked_ping.return_value = [11, "", ""] + checker.ping_gateway("4.2.2.2") + + @unittest.skipUnless(_uid == 0, "root only") + def test_ping_gateway(self): + checker = eipchecks.EIPConfigChecker() + checker.ping_gateway("4.2.2.2") + class ProviderCertCheckerTest(BaseLeapTest): -- cgit v1.2.3