Example #1
0
    def latest():
        '''returns latest probe requests'''
        format = request.args.get('format')
        if format is None:
            format = 'text'

        cur = get_db().cursor()
        # to store temp table and indices in memory
        sql = 'pragma temp_store = 2;'
        cur.execute(sql)

        sql = '''select date, mac.address, vendor.name, ssid.name, rssi from probemon
inner join mac on probemon.mac=mac.id
inner join ssid on probemon.ssid=ssid.id
inner join vendor on mac.vendor=vendor.id
order by date desc limit 100'''
        sql_args = None
        try:
            cur.execute(sql)
        except sqlite3.OperationalError as e:
            return jsonify({
                'status': 'error',
                'message': 'sqlite3 db is not accessible'
            }), 500

        # extract data from db
        text = ''
        for t, mac, vs, ssid, rssi in cur.fetchall():
            t = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(t))
            d = (t, int(rssi), ssid)
            if is_local_bit_set(mac):
                mac += ' (LAA)'
            text += f'{t}\t{mac}\t{int(rssi)}\t{vs}\n'

        resp = make_response('\n'.join(reversed(text.strip().split('\n'))))
        resp.headers['Content-Type'] = 'text/plain'
        return resp
Example #2
0
    def stats():
        '''returns stats for given macs between timestamp'''
        after = request.args.get('after')
        if after is not None:
            try:
                after = time.mktime(time.strptime(after, '%Y-%m-%dT%H:%M:%S'))
            except ValueError as v:
                raise InvalidUsage('Invalid after parameter')
        before = request.args.get('before')
        if before is not None:
            try:
                before = time.mktime(time.strptime(before,
                                                   '%Y-%m-%dT%H:%M:%S'))
            except ValueError as v:
                raise InvalidUsage('Invalid before parameter')
        macs = request.args.getlist('macs')
        rssi, zero, day = None, False, False

        cur = get_db().cursor()
        # to store temp table and indices in memory
        sql = 'pragma temp_store = 2;'
        cur.execute(sql)

        sql, sql_args = build_sql_query(after, before, macs, rssi, zero, day)
        try:
            cur.execute(sql, sql_args)
        except sqlite3.OperationalError as e:
            return jsonify({
                'status': 'error',
                'message': 'sqlite3 db is not accessible'
            }), 500

        # gather stats about each mac, same code as in stats.py
        # TODO: just import that
        macs = {}
        for row in cur.fetchall():
            mac = row[1]
            if is_local_bit_set(mac):
                # create virtual mac for LAA mac address
                mac = 'LAA'
            if mac not in macs:
                macs[mac] = {
                    'vendor': row[2],
                    'ssid': [],
                    'rssi': [],
                    'last': row[0],
                    'first': row[0]
                }
            d = macs[mac]
            if row[3] != '' and row[3] not in d['ssid']:
                d['ssid'].append(row[3])
            if row[0] > d['last']:
                d['last'] = row[0]
            if row[0] < d['first']:
                d['first'] = row[0]
            if row[4] != 0:
                d['rssi'].append(row[4])

        # sort on frequency of appearence of a mac
        tmp = [(k, len(v['rssi'])) for k, v in macs.items()]
        tmp = [m for m, _ in reversed(sorted(tmp, key=lambda k: k[1]))]

        data = []
        # dump our stats
        for m in tmp:
            v = macs[m]
            first = time.strftime('%Y-%m-%dT%H:%M:%S',
                                  time.localtime(v['first']))
            last = time.strftime('%Y-%m-%dT%H:%M:%S',
                                 time.localtime(v['last']))
            t = {
                'mac': m,
                'vendor': v['vendor'],
                'ssids': sorted(v['ssid']),
                'first': first,
                'last': last
            }
            rssi = v['rssi']
            if rssi != []:
                t.update({
                    'rssi': {
                        'count': len(rssi),
                        'min': min(rssi),
                        'max': max(rssi),
                        'avg': sum(rssi) / len(rssi),
                        'median': int(median(rssi))
                    }
                })
            data.append(t)

        return jsonify(data)
Example #3
0
    def probes():
        '''returns list of probe requests for given macs between timestamps'''
        after = request.args.get('after')
        if after is not None:
            try:
                after = time.mktime(time.strptime(after, '%Y-%m-%dT%H:%M:%S'))
            except ValueError as v:
                raise InvalidUsage('Invalid after parameter')
        before = request.args.get('before')
        if before is not None:
            try:
                before = time.mktime(time.strptime(before,
                                                   '%Y-%m-%dT%H:%M:%S'))
            except ValueError as v:
                raise InvalidUsage('Invalid before parameter')
        rssi = request.args.get('rssi')
        if rssi is not None:
            try:
                rssi = int(rssi)
            except ValueError as v:
                raise InvalidUsage('Invalid rssi value')

        macs = request.args.get('macs')
        zero = request.args.get('zero')
        today = request.args.get('today')
        output = request.args.get('output', default='json')

        cur = get_db().cursor()
        # to store temp table and indices in memory
        sql = 'pragma temp_store = 2;'
        cur.execute(sql)

        now = time.time()
        sql, sql_args = build_sql_query(after, before, macs, rssi, zero, today)
        try:
            cur.execute(sql, sql_args)
        except sqlite3.OperationalError as e:
            return jsonify({
                'status': 'error',
                'message': 'sqlite3 db is not accessible'
            }), 500

        vendor = {}
        ts = {}
        if after is not None:
            starting_ts = int(after * 1000)
        elif today:
            starting_ts = int((now - 24 * 60 * 60) * 1000)
        else:
            sql = 'select date from probemon order by date limit 1;'
            c.execute(sql)
            starting_ts = int(c.fetchone()[0] * 1000)
        # extract data from db
        for t, mac, vs, ssid, rssi in cur.fetchall():
            #t = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(t))
            d = (int(t * 1000 - starting_ts), int(rssi), ssid)
            if is_local_bit_set(mac):
                mac = 'LAA'
            if mac not in ts.keys():
                ts[mac] = [d]
                vendor[mac] = vs
            else:
                ts[mac].append(d)

        data = []
        # recollection
        for m in ts.keys():
            if m == 'LAA' or m.startswith(config['merged']):
                continue  # will deal with them later
            known = m in config['knownmac']
            ssids = list(set(f[2] for f in ts[m]))
            t = {
                'mac':
                m,
                'known':
                known,
                'vendor':
                vendor[m],
                'ssids':
                ssids,
                'starting_ts':
                starting_ts,
                'probereq': [{
                    'ts': f[0],
                    'rssi': f[1],
                    'ssid': ssids.index(f[2])
                } for f in ts[m]]
            }
            if len(t['probereq']) > 3:
                data.append(t)
        data.sort(key=lambda x: len(x['probereq']), reverse=True)
        # LAA
        if 'LAA' in ts.keys():
            ssids = list(set(f[2] for f in ts['LAA']))
            t = {
                'mac':
                'LAA',
                'vendor':
                u'UNKNOWN',
                'ssids':
                ssids,
                'starting_ts':
                starting_ts,
                'probereq': [{
                    'ts': f[0],
                    'rssi': f[1],
                    'ssid': ssids.index(f[2])
                } for f in ts['LAA']]
            }
            data.append(t)
        # MERGED
        for m in config['merged']:
            mm = [ma for ma in ts.keys() if ma.startswith(m)]
            p = []
            for n in mm:
                p.extend(ts[n])
            ssids = list(set(f[2] for f in p))
            if len(p) == 0:
                continue
            p.sort(key=lambda x: x[0])
            t = {
                'mac':
                m,
                'vendor':
                u'UNKNOWN',
                'ssids':
                ssids,
                'starting_ts':
                starting_ts,
                'probereq': [{
                    'ts': f[0],
                    'rssi': f[1],
                    'ssid': ssids.index(f[2])
                } for f in p]
            }
            data.append(t)

        if output == 'json':
            resp = make_response(jsonify(data))
        elif output == 'protobuf':
            res = probe_pb2.MyData()
            for t in data:
                p = res.probes.add()
                p.mac = t['mac']
                p.vendor = t['vendor']
                p.starting_ts = t['starting_ts']
                for s in t['ssids']:
                    sl = p.ssids.add()
                    sl.name = s
                try:
                    p.known = t['known']
                except KeyError as k:
                    p.known = False
                for f in t['probereq']:
                    pr = p.probereq.add()
                    pr.timestamp = f['ts']
                    pr.rssi = f['rssi']
                    pr.ssid = f['ssid']
            resp = make_response(res.SerializeToString())
            resp.headers['Content-Type'] = 'application/x-protobuf'

        if not today:
            resp.headers['Cache-Control'] = 'max-age=21600'
        return resp
Example #4
0
    def probes():
        '''returns list of probe requests for given macs between timestamps'''
        after = request.args.get('after')
        if after is not None:
            try:
                after = time.mktime(time.strptime(after, '%Y-%m-%dT%H:%M:%S'))
            except ValueError as v:
                raise InvalidUsage('Invalid after parameter')
        before = request.args.get('before')
        if before is not None:
            try:
                before = time.mktime(time.strptime(before,
                                                   '%Y-%m-%dT%H:%M:%S'))
            except ValueError as v:
                raise InvalidUsage('Invalid before parameter')
        rssi = request.args.get('rssi')
        if rssi is not None:
            try:
                rssi = int(rssi)
            except ValueError as v:
                raise InvalidUsage('Invalid rssi value')

        macs = request.args.get('macs')
        zero = request.args.get('zero')
        today = request.args.get('today')

        cur = get_db().cursor()
        # to store temp table and indices in memory
        sql = 'pragma temp_store = 2;'
        cur.execute(sql)

        sql, sql_args = build_sql_query(after, before, macs, rssi, zero, today)
        try:
            cur.execute(sql, sql_args)
        except sqlite3.OperationalError as e:
            return jsonify({
                'status': 'error',
                'message': 'sqlite3 db is not accessible'
            }), 500

        vendor = {}
        ts = {}
        # extract data from db
        for t, mac, vs, ssid, rssi in cur.fetchall():
            #t = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(t))
            d = (t, int(rssi), ssid)
            if is_local_bit_set(mac):
                mac = 'LAA'
            if mac not in ts.keys():
                ts[mac] = [d]
                vendor[mac] = vs
            else:
                ts[mac].append(d)

        data = []
        # recollection
        for m in ts.keys():
            if m == 'LAA' or m.startswith(config.MERGED):
                continue  # will deal with them later
            known = m in config.KNOWNMAC
            ssids = list(set(f[2] for f in ts[m]))
            t = {
                'mac':
                m,
                'known':
                known,
                'vendor':
                vendor[m],
                'ssids':
                ssids,
                'probereq': [{
                    'ts': int(f[0] * 1000),
                    'rssi': f[1],
                    'ssid': ssids.index(f[2])
                } for f in ts[m]]
            }
            if len(t['probereq']) > 3:
                data.append(t)
        data.sort(key=lambda x: len(x['probereq']), reverse=True)
        # LAA
        if 'LAA' in ts.keys():
            ssids = list(set(f[2] for f in ts['LAA']))
            t = {
                'mac':
                'LAA',
                'vendor':
                u'UNKNOWN',
                'ssids':
                ssids,
                'probereq': [{
                    'ts': int(f[0] * 1000),
                    'rssi': f[1],
                    'ssid': ssids.index(f[2])
                } for f in ts['LAA']]
            }
            data.append(t)
        # MERGED
        for m in config.MERGED:
            mm = [ma for ma in ts.keys() if ma.startswith(m)]
            p = []
            for n in mm:
                p.extend(ts[n])
            ssids = list(set(f[2] for f in p))
            if len(p) == 0:
                continue
            p.sort(key=lambda x: x[0])
            t = {
                'mac':
                m,
                'vendor':
                u'UNKNOWN',
                'ssids':
                ssids,
                'probereq': [{
                    'ts': int(f[0] * 1000),
                    'rssi': f[1],
                    'ssid': ssids.index(f[2])
                } for f in p]
            }
            data.append(t)

        resp = make_response(jsonify(data))
        if not today:
            resp.headers['Cache-Control'] = 'max-age=21600'
        return resp

        @app.errorhandler(InvalidUsage)
        def handle_invalid_usage(error):
            response = jsonify(error.to_dict())
            response.status_code = error.status_code
            return response