[or-cvs] r23884: {arm} Supporting FreeBSD connection resolvers and sockstat resolut (in arm/trunk: . src/interface src/util)

Damian Johnson atagar1 at gmail.com
Sun Dec 5 03:07:36 UTC 2010


Author: atagar
Date: 2010-12-05 03:07:36 +0000 (Sun, 05 Dec 2010)
New Revision: 23884

Modified:
   arm/trunk/ChangeLog
   arm/trunk/TODO
   arm/trunk/src/interface/controller.py
   arm/trunk/src/util/connections.py
Log:
Supporting FreeBSD connection resolvers and sockstat resolution as a general resolver (thanks to Fabian and Hans).



Modified: arm/trunk/ChangeLog
===================================================================
--- arm/trunk/ChangeLog	2010-12-01 20:59:59 UTC (rev 23883)
+++ arm/trunk/ChangeLog	2010-12-05 03:07:36 UTC (rev 23884)
@@ -1,6 +1,6 @@
 CHANGE LOG
 
-11/27/10 - version 1.4.0
+11/27/10 - version 1.4.0 (r23873)
 Introducing a new page for managing tor's configuration, along with several other improvements.
 
     * added: editor for the tor configuration, providing:

Modified: arm/trunk/TODO
===================================================================
--- arm/trunk/TODO	2010-12-01 20:59:59 UTC (rev 23883)
+++ arm/trunk/TODO	2010-12-05 03:07:36 UTC (rev 23884)
@@ -41,9 +41,22 @@
           - 'safe' option that restricts to read-only access (start with this)
           - issue sighup reset
       [ ] low hanging fruit from the "client mode use cases" below
+      [ ] store resources (config and cache) in the home directory (suggestion
+          by Sebastian)
+      [ ] note TERM="rxvt-unicode" as possible fix when graph isn't visible
+          while using screen
+      [ ] include short, summary descriptions instead of man contents in
+          the listing
+      [ ] add warning when arm cpu resource usage is high that the -b flag
+          would be suggested (caught by Clete - "arm went from using 30% of
+          the CPU time to 1% constant" on a 360MHz machine)
+      [ ] deb issue: "one issue I noticed was that, again, the source package
+          is not idempotent, that is to say if I unpack the .dsc and build the
+          package I end up with a different .diff.gz"
   * release prep
     * pylint --indent-string="  " --disable=C,R interface/foo.py | less
     * double check __init__.py and README for changes
+    * Gentoo notification (contact NightMonkey)
 
 - Roadmap for version 1.4.2
   [ ] refactor panels
@@ -68,6 +81,10 @@
             - http://www.linuxjournal.com/article/5737
 
 - Bugs
+  * The manpage layout is system dependent, so the scraper needs to be more
+    resilient against being confused by whitespace. Another improvement is
+    including fallback results if the man page can't be parsed (suggested by
+    rransom, issue caught by NightMonkey).
   * Log deduplication is currently an n^2 operation. Hence it can't handle
     large logs (for instance, when at the DEBUG runlevel). Currently we're
     timing out the function if it takes too long, but a more efficient method

Modified: arm/trunk/src/interface/controller.py
===================================================================
--- arm/trunk/src/interface/controller.py	2010-12-01 20:59:59 UTC (rev 23883)
+++ arm/trunk/src/interface/controller.py	2010-12-05 03:07:36 UTC (rev 23884)
@@ -1401,7 +1401,7 @@
         panels["conn"].sortConnections()
     elif page == 1 and (key == ord('u') or key == ord('U')):
       # provides menu to pick identification resolving utility
-      optionTypes = [None, connections.CMD_NETSTAT, connections.CMD_SS, connections.CMD_LSOF]
+      optionTypes = [None, connections.CMD_NETSTAT, connections.CMD_SS, connections.CMD_LSOF, connections.CMD_SOCKSTAT, connections.CMD_BSD_SOCKSTAT, connections.CMD_BSD_PROCSTAT]
       options = ["auto"] + [connections.CMD_STR[util] for util in optionTypes[1:]]
       
       initialSelection = connections.getResolver("tor").overwriteResolver # enums correspond to indices

Modified: arm/trunk/src/util/connections.py
===================================================================
--- arm/trunk/src/util/connections.py	2010-12-01 20:59:59 UTC (rev 23883)
+++ arm/trunk/src/util/connections.py	2010-12-05 03:07:36 UTC (rev 23884)
@@ -5,12 +5,18 @@
 - netstat   netstat -npt | grep <pid>/<process>
 - ss        ss -p | grep "\"<process>\",<pid>"
 - lsof      lsof -nPi | grep "<process>\s*<pid>.*(ESTABLISHED)"
+- sockstat  sockstat | egrep "<process>\s*<pid>.*ESTABLISHED"
 
-all queries dump its stderr (directing it to /dev/null). Unfortunately FreeBSD
-lacks support for the needed netstat flags and has a completely different
-program for 'ss', so this is quite likely to fail there.
+all queries dump its stderr (directing it to /dev/null).
+
+FreeBSD lacks support for the needed netstat flags and has a completely
+different program for 'ss'. However, there's a couple other options (thanks to
+Fabian Keil and Hans Schnehl):
+- sockstat    sockstat -4 | egrep '<process>\s*<pid>' | grep -v '*:*'
+- procstat    procstat -f 'pgrep <process>' | grep '<pid>' | grep -v '0.0.0.0:0'
 """
 
+import os
 import sys
 import time
 import threading
@@ -18,8 +24,13 @@
 from util import log, sysTools
 
 # enums for connection resolution utilities
-CMD_NETSTAT, CMD_SS, CMD_LSOF = range(1, 4)
-CMD_STR = {CMD_NETSTAT: "netstat", CMD_SS: "ss", CMD_LSOF: "lsof"}
+CMD_NETSTAT, CMD_SS, CMD_LSOF, CMD_SOCKSTAT, CMD_BSD_SOCKSTAT, CMD_BSD_PROCSTAT = range(1, 7)
+CMD_STR = {CMD_NETSTAT: "netstat",
+           CMD_SS: "ss",
+           CMD_LSOF: "lsof",
+           CMD_SOCKSTAT: "sockstat",
+           CMD_BSD_SOCKSTAT: "sockstat (bsd)",
+           CMD_BSD_PROCSTAT: "procstat (bsd)"}
 
 # If true this provides new instantiations for resolvers if the old one has
 # been stopped. This can make it difficult ensure all threads are terminated
@@ -46,11 +57,20 @@
 # tor  9912  atagar  20u  IPv4  33453  TCP 127.0.0.1:9051->127.0.0.1:53308
 RUN_LSOF = "lsof -nPi | grep \"%s\s*%s.*(ESTABLISHED)\""
 
+# output:
+# atagar  tor  3475  tcp4  127.0.0.1:9051  127.0.0.1:38942  ESTABLISHED
+# *note: this isn't available by default under ubuntu
+RUN_SOCKSTAT = "sockstat | egrep \"%s\s*%s.*ESTABLISHED\""
+
+RUN_BSD_SOCKSTAT = "sockstat -4 | egrep '%s\s*%s' | grep -v '*:*'"
+RUN_BSD_PROCSTAT = "procstat -f 'pgrep %s' | grep '%s' | grep -v '0.0.0.0:0'"
+
 RESOLVERS = []                      # connection resolvers available via the singleton constructor
 RESOLVER_FAILURE_TOLERANCE = 3      # number of subsequent failures before moving on to another resolver
 RESOLVER_SERIAL_FAILURE_MSG = "Querying connections with %s failed, trying %s"
 RESOLVER_FINAL_FAILURE_MSG = "All connection resolvers failed"
 CONFIG = {"queries.connections.minRate": 5,
+          "log.connResolverOptions": log.INFO,
           "log.connLookupFailed": log.INFO,
           "log.connLookupFailover": log.NOTICE,
           "log.connLookupAbandon": log.WARN,
@@ -78,7 +98,11 @@
   
   if resolutionCmd == CMD_NETSTAT: cmd = RUN_NETSTAT % (processPid, processName)
   elif resolutionCmd == CMD_SS: cmd = RUN_SS % (processName, processPid)
-  else: cmd = RUN_LSOF % (processName, processPid)
+  elif resolutionCmd == CMD_LSOF: cmd = RUN_LSOF % (processName, processPid)
+  elif resolutionCmd == CMD_SOCKSTAT: cmd = RUN_SOCKSTAT % (processName, processPid)
+  elif resolutionCmd == CMD_BSD_SOCKSTAT: cmd = RUN_BSD_SOCKSTAT % (processName, processPid)
+  elif resolutionCmd == CMD_BSD_PROCSTAT: cmd = RUN_BSD_PROCSTAT % (processName, processPid)
+  else: raise ValueError("Unrecognized resolution type: %s" % resolutionCmd)
   
   # raises an IOError if the command fails or isn't available
   results = sysTools.call(cmd)
@@ -93,10 +117,19 @@
     if resolutionCmd == CMD_NETSTAT or resolutionCmd == CMD_SS:
       localIp, localPort = comp[3].split(":")
       foreignIp, foreignPort = comp[4].split(":")
-    else:
+    elif resolutionCmd == CMD_LSOF:
       local, foreign = comp[8].split("->")
       localIp, localPort = local.split(":")
       foreignIp, foreignPort = foreign.split(":")
+    elif resolutionCmd == CMD_SOCKSTAT:
+      localIp, localPort = comp[4].split(":")
+      foreignIp, foreignPort = comp[5].split(":")
+    elif resolutionCmd == CMD_BSD_SOCKSTAT:
+      localIp, localPort = comp[5].split(":")
+      foreignIp, foreignPort = comp[6].split(":")
+    elif resolutionCmd == CMD_BSD_PROCSTAT:
+      localIp, localPort = comp[9].split(":")
+      foreignIp, foreignPort = comp[10].split(":")
     
     conn.append((localIp, localPort, foreignIp, foreignPort))
   
@@ -216,6 +249,7 @@
     overwriteResolver - method of resolution (uses default if None)
     * defaultResolver - resolver used by default (None if all resolution
                         methods have been exhausted)
+    resolverOptions   - resolvers to be cycled through (differ by os)
     
     * read-only
   """
@@ -243,9 +277,16 @@
     self.overwriteResolver = None
     self.defaultResolver = CMD_NETSTAT
     
+    osType = os.uname()[0]
+    if osType == "FreeBSD": self.resolverOptions = [CMD_BSD_SOCKSTAT, CMD_BSD_PROCSTAT]
+    else: self.resolverOptions = [CMD_NETSTAT, CMD_SS, CMD_LSOF, CMD_SOCKSTAT]
+    
+    resolverLabels = ", ".join([CMD_STR[option] for option in self.resolverOptions])
+    log.log(CONFIG["log.connResolverOptions"], "Operating System: %s, Connection Resolvers: %s" % (osType, resolverLabels))
+    
     # sets the default resolver to be the first found in the system's PATH
     # (left as netstat if none are found)
-    for resolver in [CMD_NETSTAT, CMD_SS, CMD_LSOF]:
+    for resolver in self.resolverOptions:
       if sysTools.isAvailable(CMD_STR[resolver]):
         self.defaultResolver = resolver
         break
@@ -320,7 +361,7 @@
             
             # pick another (non-blacklisted) resolver
             newResolver = None
-            for r in [CMD_NETSTAT, CMD_SS, CMD_LSOF]:
+            for r in self.resolverOptions:
               if not r in self._resolverBlacklist:
                 newResolver = r
                 break



More information about the tor-commits mailing list