[tor-commits] [ooni-probe/master] * Rewrite of echo.

isis at torproject.org isis at torproject.org
Fri Nov 16 00:50:07 UTC 2012


commit 56ae275afcd3ca2517dd9e8ff8ec6b83448c34a6
Author: Isis Lovecruft <isis at torproject.org>
Date:   Thu Nov 15 23:09:46 2012 +0000

    * Rewrite of echo.
---
 nettests/bridge_reachability/echo.py |  176 ++++++++++++++++------------------
 1 files changed, 83 insertions(+), 93 deletions(-)

diff --git a/nettests/bridge_reachability/echo.py b/nettests/bridge_reachability/echo.py
index 5198766..40436e7 100644
--- a/nettests/bridge_reachability/echo.py
+++ b/nettests/bridge_reachability/echo.py
@@ -6,59 +6,57 @@
 #  +---------+
 #     A simple ICMP-8 ping test.
 #
-# :author: Isis Lovecruft
-# :version: 0.0.1-pre-alpha
-# :license: (c) 2012 Isis Lovecruft
+# @authors: Isis Lovecruft, <isis at torproject.org>
+# @version: 0.0.2-pre-alpha
+# @license: copyright (c) 2012 Isis Lovecruft
 #           see attached LICENCE file
 #
 
 import os
 import sys
 
-from pprint           import pprint
-
-from twisted.internet import reactor
-from twisted.plugin   import IPlugin
 from twisted.python   import usage
-from ooni.nettest     import NetTestCase
-from ooni.utils       import log, Storage
-from ooni.utils.net   import PermissionsError, IfaceError
+from twisted.internet import reactor, defer
+from ooni             import nettest
+from ooni.utils       import log, net, Storage
 
 try:
-    from scapy.all             import sr1, IP, ICMP        ## XXX v4/v6?
+    from scapy.all             import IP, ICMP
+    from scapy.all             import sr1
     from ooni.lib              import txscapy
     from ooni.lib.txscapy      import txsr, txsend
     from ooni.templates.scapyt import BaseScapyTest
 except:
     log.msg("This test requires scapy, see www.secdev.org/projects/scapy")
 
-class EchoTest(BaseScapyTest):
+class UsageOptions(usage.Options):
+    optParameters = [
+        ['dst', 'd', None, 'Host IP to ping'],
+        ['file', 'f', None, 'File of list of IPs to ping'],
+        ['interface', 'i', None, 'Network interface to use'],
+        ['count', 'c', 1, 'Number of packets to send', int],
+        ['size', 's', 56, 'Number of bytes to send in ICMP data field', int],
+        ['ttl', 'l', 25, 'Set the IP Time to Live', int],
+        ['timeout', 't', 2, 'Seconds until timeout if no response', int],
+        ['pcap', 'p', None, 'Save pcap to this file'],
+        ['receive', 'r', True, 'Receive response packets']]
+
+class EchoTest(nettest.NetTestCase):
     """
     xxx fill me in
     """
     name         = 'echo'
     author       = 'Isis Lovecruft <isis at torproject.org>'
-    description  = 'A simple ICMP-8 test to see if a host is reachable.'
-    version      = '0.0.1'
-    inputFile    = ['file', 'f', None, 'File of list of IPs to ping']
+    description  = 'A simple ping test to see if a host is reachable.'
+    version      = '0.0.2'
     requiresRoot = True
 
-    optParameters = [
-        ['interface', 'i', None, 'Network interface to use'],
-        ['count', 'c', 5, 'Number of packets to send', int],
-        ['size', 's', 56, 'Number of bytes to send in ICMP data field', int],
-        ['ttl', 'l', 25, 'Set the IP Time to Live', int],
-        ['timeout', 't', 2, 'Seconds until timeout if no response', int],
-        ['pcap', 'p', None, 'Save pcap to this file'],
-        ['receive', 'r', True, 'Receive response packets']
-        ]
+    usageOptions    = UsageOptions
+    #requiredOptions = ['dst']
 
     def setUp(self, *a, **kw):
-        '''
-        :ivar ifaces:
-            Struct returned from getifaddrs(3) and turned into a tuple in the
-            form (*ifa_name, AF_FAMILY, *ifa_addr)
-        '''
+        self.destinations = {}
+
         if self.localOptions:
             for key, value in self.localOptions.items():
                 log.debug("setting self.%s = %s" % (key, value))
@@ -67,76 +65,68 @@ class EchoTest(BaseScapyTest):
         self.timeout *= 1000            ## convert to milliseconds
 
         if not self.interface:
-            log.msg("No network interface specified!")
+            try:
+                iface = net.getDefaultIface()
+            except Exception, e:
+                log.msg("No network interface specified!")
+                log.err(e)
+            else:
+                log.msg("Using system default interface: %s" % iface)
+                self.interface = iface
 
         if self.pcap:
             try:
                 self.pcapfile = open(self.pcap, 'a+')
             except:
                 log.msg("Unable to write to pcap file %s" % self.pcap)
-                self.pcapfile = None
-
-        try:
-            assert os.path.isfile(self.file)
-            fp = open(self.file, 'r')
-        except Exception, e:
-            hosts = ['8.8.8.8', '38.229.72.14']
-            log.err(e)
-        else:
-            self.inputs = self.inputProcessor(fp)
-        self.removePorts(hosts)
-
-        log.debug("Initialization of %s test completed with:\n%s"
-                  % (self.name, ''.join(self.__dict__)))
-
-    @staticmethod
-    def inputParser(self, one_input):
-        log.debug("Removing possible ports from host addresses...")
-        log.debug("Initial inputs:\n%s" % pprint(inputs))
-
-        #host = [h.rsplit(':', 1)[0] for h in inputs]
-        host = h.rsplit(':', 1)[0]
-        log.debug("Inputs converted to:\n%s" % hosts)
-
-        return host
-
-    def tryInterfaces(self, ifaces):
-        try:
-            from scapy.all import sr1   ## we want this check to be blocking
-        except:
-            log.msg("This test requires scapy: www.secdev.org/projects/scapy")
-            raise SystemExit
-
-        ifup = {}
-        while ifaces:
-            for ifname, ifaddr in ifaces:
-                log.debug("Currently testing network capabilities of interface"
-                          + "%s  by sending a packet to our address %s"
-                          % (ifname, ifaddr))
-                try:
-                    pkt = IP(dst=ifaddr)/ICMP()
-                    ans, unans = sr(pkt, iface=ifname, timeout=self.timeout)
-                except Exception, e:
-                    raise PermissionsError if e.find("Errno 1") else log.err(e)
-                else:
-                    ## xxx i think this logic might be wrong
-                    log.debug("Interface test packet\n%s\n\n%s"
-                              % (pkt.summary(), pkt.show2()))
-                    if ans.summary():
-                        log.info("Received answer for test packet on interface"
-                                 +"%s :\n%s" % (ifname, ans.summary()))
-                        ifup.update(ifname, ifaddr)
-                    else:
-                        log.info("Our interface test packet was unanswered:\n%s"
-                                 % unans.summary())
-
-        if len(ifup) > 0:
-            log.msg("Discovered the following working network interfaces: %s"
-                    % ifup)
-            return ifup
+            else:
+                self.pcap = net.capturePacket(self.pcapfile)
+
+        if not self.dst:
+            if self.file:
+                self.dstProcessor(self.file)
+                for key, value in self.destinations.items():
+                    for label, data in value.items():
+                        if not 'ans' in data:
+                            self.dst = label
         else:
-            raise IfaceError("Could not find a working network interface.")
+            self.addDest(self.dst)
+        log.debug("self.dst is now: %s" % self.dst)
 
-    def test_icmp(self):
-        return self.sr(IP(dst=self.input)/ICMP())
+        log.debug("Initialization of %s test completed." % self.name)
+
+    def addDest(self, dest):
+        d = dest.strip()
+        self.destinations[d] = {'dst_ip': d}
+
+    def dstProcessor(self, inputfile):
+        from ipaddr import IPAddress
 
+        if os.path.isfile(inputfile):
+            with open(inputfile) as f:
+                for line in f.readlines():
+                    if line.startswith('#'):
+                        continue
+                    self.addDest(line)
+
+    def test_icmp(self):
+        def process_response(echo_reply, dest):
+           ans, unans = echo_reply
+           if ans:
+               log.msg("Recieved echo reply from %s: %s" % (dest, ans))
+           else:
+               log.msg("No reply was received from %s. Possible censorship event." % dest)
+               log.debug("Unanswered packets: %s" % unans)
+           self.report[dest] = echo_reply
+
+        for label, data in self.destinations.items():
+            reply = sr1(IP(dst=lebal)/ICMP())
+            process = process_reponse(reply, label)
+
+        #(ans, unans) = ping
+        #self.destinations[self.dst].update({'ans': ans,
+        #                                    'unans': unans,
+        #                                    'response_packet': ping})
+        #return ping
+
+        #return reply





More information about the tor-commits mailing list