pvl.wlan-sta: track openwrt hostapd syslog wlan sta activity
authorTero Marttila <terom@paivola.fi>
Thu, 04 Jul 2013 03:49:55 +0300
changeset 236 7b37f84b17cc
parent 235 a34e7260568b
child 237 3534d31282b3
pvl.wlan-sta: track openwrt hostapd syslog wlan sta activity
bin/pvl.wlan-sta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/pvl.wlan-sta	Thu Jul 04 03:49:55 2013 +0300
@@ -0,0 +1,131 @@
+#!/usr/bin/python
+
+"""
+    Analyze WLAN STA logs.
+
+        Jul  3 23:05:04 buffalo-g300n-647682 daemon.info hostapd: wlan0-1: STA aa:bb:cc:dd:ee:ff WPA: group key handshake completed (RSN)
+
+"""
+
+__version__ = '0.1'
+
+import pvl.args
+import pvl.syslog.args
+import pvl.rrd.hosts
+
+import optparse
+import logging; log = logging.getLogger('main')
+
+WLAN_STA_PROG = 'hostapd'
+
+def parse_argv (argv, doc = __doc__) :
+    """
+        Parse command-line argv, returning (options, args).
+    """
+
+    prog = argv.pop(0)
+    args = argv
+
+    # optparse
+    parser = optparse.OptionParser(
+        prog        = prog,
+        usage       = '%prog: [options] [<input.txt> [...]]',
+        version     = __version__,
+        description = doc,
+    )
+
+    # common
+    parser.add_option_group(pvl.args.parser(parser))
+    parser.add_option_group(pvl.syslog.args.parser(parser, prog=WLAN_STA_PROG))
+
+    parser.add_option('--interfaces', metavar='PATH',
+            help="Load interface/node names from mapping file")
+
+    parser.set_defaults(
+    )
+
+    # parse
+    options, args = parser.parse_args(args)
+
+    # apply
+    pvl.args.apply(options)
+
+    return options, args
+
+import re
+
+class HostapdHandler (object) :
+    HOSTAPD_STA_RE = re.compile(r'(?P<wlan>.+?): STA (?P<sta>.+?) (?P<msg>.+)')
+
+    def __init__ (self, interface_map=None) :
+        """
+            interface_map       - {(hostname, interface): (nodename, wlan)}
+        """
+        self.interface_map = interface_map
+
+    def parse (self, item) :
+        """
+            Parse fields from a hostapd syslog message.
+        """
+        
+        match = self.HOSTAPD_STA_RE.match(item['msg'])
+
+        if not match :
+            return None
+
+        return dict(item, **match.groupdict())
+
+    def build_sta (self, match) :
+        ap, wlan = match['host'], match['wlan']
+        
+        # override?
+        if self.interface_map :
+            mapping = self.interface_map.get((ap, wlan))
+
+            if mapping :
+                ap, wlan = mapping
+        
+        build = dict(
+                timestamp       = match['timestamp'],
+                ap              = ap,
+                wlan            = wlan,
+                sta             = match['sta'],
+                msg             = match['msg'],
+        )
+
+
+        return build
+
+def main (argv) :
+    options, args = parse_argv(argv)
+
+    if options.interfaces :
+        interfaces = dict(pvl.rrd.hosts.map_interfaces(options, open(options.interfaces)))
+    else :
+        interfaces = None
+
+    # syslog
+    log.info("Open up syslog...")
+    syslog = pvl.syslog.args.apply(options)
+    handler = HostapdHandler(interface_map=interfaces)
+
+    log.info("Enter mainloop...")
+    for source in syslog.main() :
+        for item in source:
+            match = handler.parse(item)
+
+            if not match :
+                continue
+            elif 'sta' in match :
+                sta = handler.build_sta(match)
+            else :
+                continue
+        
+            print "{ap:>30}/{wlan:10} {sta:20} : {msg}".format(**sta)
+
+    return 0
+    
+if __name__ == '__main__':
+    import sys
+
+    sys.exit(main(sys.argv))