bin/pvl.wlan-sta
author Tero Marttila <terom@paivola.fi>
Thu, 04 Jul 2013 03:49:55 +0300
changeset 236 7b37f84b17cc
child 238 9702bfb124f6
permissions -rwxr-xr-x
pvl.wlan-sta: track openwrt hostapd syslog wlan sta activity
#!/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))