#!/usr/bin/python3 import json import netaddr import gzip import re import os import sys import pprint import requests MAC_URL = 'http://macvendors.co/api/%s' def getHardwareModelFromEntry(d): hardware_model = "UNKNOWN" if d != None: if "hardware" in d: if "model" in d["hardware"]: hardware_model = d["hardware"]["model"] return hardware_model def ipv62mac(ipv6): # remove subnet info if given subnetIndex = ipv6.find("/") if subnetIndex != -1: ipv6 = ipv6[:subnetIndex] ipv6Parts = ipv6.split(":") macParts = [] for ipv6Part in ipv6Parts[-4:]: while len(ipv6Part) < 4: ipv6Part = "0" + ipv6Part macParts.append(ipv6Part[:2]) macParts.append(ipv6Part[-2:]) # modify parts to match MAC value macParts[0] = "%02x" % (int(macParts[0], 16) ^ 2) del macParts[4] del macParts[3] return ":".join(macParts) class LogRecord: def __init__(self,record): record = record.replace("%2B","+") regex = r'(fd21.*) - - \[(.*) "GET /gluon/(.*)/sysupgrade/gluon-ffs-([0-9]\.[0-9]\+[0-9]+-[0-9]+-[0-9]+-g\.[0-9a-z]+-s\.[0-9a-z]+)-(.*)\ HTTP/1.1" ([0-9]+) [0-9]+ "-" "(.*)"' result = re.search(regex,record) try: groups = result.groups() except: print(record) print("error parsing record") sys.exit(1) self.ipv6 = groups[0] self.date = groups[1] self.branch = groups[2] self.release = groups[3] self.model = groups[4] self.status = groups[5] self.agent = groups[6] self.segment = int(self.ipv6.split(":")[2][2:]) try: allFirmwareDownloads = json.load(open("firmwareDownloads.json","r")) except: allFirmwareDownloads = [] access = "" try: #for i in range(2,15): # access += gzip.open("/var/log/nginx/access.log.%i.gz"%(i),"rt").read() access += open("/var/log/nginx/access.log.1").read() access += open("/var/log/nginx/access.log").read() except: print("not using /var/log/nginx/access.log") try: access += open("access.log").read() except: pass allDownloads = access.strip().split("\n") allNewFirmwareDownloads = [l for l in allDownloads if l.startswith("fd21:") and "sysupgrade" in l and "manifest" not in l] for f in allNewFirmwareDownloads: if f not in allFirmwareDownloads: allFirmwareDownloads.append(f) json.dump(allFirmwareDownloads,open("firmwareDownloads.json","w"),sort_keys=True, indent=4, separators=(',', ': ')) nodesdbFilename = "/home/www/html/netinfo/json/nodesdb.json" if not os.path.isfile(nodesdbFilename): nodesdbFilename = "nodesdb.json" data = json.load(open(nodesdbFilename)) for download in allFirmwareDownloads: r = LogRecord(download) mac = ipv62mac(r.ipv6) if mac in data: d = data[mac] currentRelease = d["software"]["firmware"]["release"] status = d["status"] hostname = d["hostname"] hardware_model = getHardwareModelFromEntry(d) if currentRelease < r.release: print("%s (%s) %s -> %s Segment %i %s status %s @ %s" % (mac, hostname, currentRelease, r.release, r.segment, hardware_model, status, r.date)) else: #request = requests.get(MAC_URL % mac) #pprint.pprint(request.json()) print("%s %s with agent %s seems not to be a node @ %s"%(r.ipv6,mac,r.agent,r.date))