📄 machinetracker.py
字号:
# -*- coding: ISO8859-1 -*-# $Id: machinetracker.py 3548 2006-07-17 11:35:38Z mortenv $## Copyright 2003, 2004 Norwegian University of Science and Technology# Copyright 2006 UNINETT AS## This file is part of Network Administration Visualized (NAV)## NAV is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## NAV is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with NAV; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA### Authors: Sigurd Gartmann <sigurd-nav@brogar.org>#from __future__ import generators# Catch the test case where we import this module outside the# mod_python environmentif 'apache' not in globals(): try: from mod_python import apache except ImportError: apache = Nonefrom pprint import pprint,pformatfrom mx import DateTimefrom socket import gethostbyaddr,gethostbyname,herrorimport refrom nav import dbfrom nav.web.URI import URIfrom nav.web.templates.MachineTrackerTemplate import MachineTrackerTemplateimport IPyimport logginglogger = logging.getLogger("nav.web.machinetracker")connection = db.getConnection('webfront', 'manage')database = connection.cursor()def handler(req): global hostCache hostCache = {} args = URI(req.unparsed_uri) section = "" s = re.search("\/(\w+?)(?:\/$|\?|\&|$)",req.uri) if s: section = s.group(1) page = MachineTrackerTemplate() page.tableCam = None page.tableArp = None page.tableSwp = None page.errors = [] tracker = None if section.lower() == "mac": page.form = MACForm(args.get("mac"), args.get("days"), args.get("dns"), args.get("aip"), args.get("naip")) if args.get("mac"): tracker = MACSQLQuery(args.get("mac"), args.get("days")) page.tableCam = tracker elif section.lower() in ("switchports", "switchport", "swport", "port", "swp"): page.form = SwPortForm(args.get("switch"), args.get("module"), args.get("port"), args.get("days"), args.get("dns"), args.get("aip"), args.get("naip")) if args.get("switch"): tracker = SwPortSQLQuery(args.get("switch"), args.get("module"), args.get("port"), args.get("days")) page.tableSwp = tracker else: prefixid = args.get("prefixid") if prefixid: sql = "select netaddr from prefix where prefixid=%s" database.execute(sql, (prefixid,)) subnet = IPy.IP(database.fetchone()[0]) from_ip = subnet[0] to_ip = subnet[-1] else: from_ip = args.get("from_ip") if from_ip: try: from_ip = IPy.IP(from_ip) except ValueError: page.errors.append('%s is not a valid IP address' % \ repr(from_ip)) to_ip = args.get("to_ip") if to_ip: try: to_ip = IPy.IP(to_ip) except ValueError: page.errors.append('%s is not a valid IP address' % \ repr(to_ip)) page.form = IPForm(from_ip, to_ip, args.get("days"), args.get("dns"), args.get("aip"), args.get("naip")) if len(page.errors) == 0 and (from_ip or to_ip): # If only one IP field was filled, use the same value for # both from- and to-fields. Perform the old switcheroo if # the latter IP is greater than the former. if from_ip and not to_ip: to_ip = from_ip elif to_ip and not from_ip: from_ip = to_ip elif from_ip > to_ip: (from_ip, to_ip) = (to_ip, from_ip) tracker = IPSQLQuery(from_ip, to_ip, args.get("days")) page.tableArp = tracker if tracker: tracker.loadTable(args.get("dns"), args.get("aip"), args.get("naip")) if page.tableCam: ipTracker = IPSQLQuery(days = args.get("days"), macTracker = tracker) ipTracker.loadTable(dns=args.get("dns")) page.tableArp = ipTracker req.content_type = "text/html" req.send_http_header() req.write(page.respond()) return apache.OKclass MachineTrackerSQLQuery: def __init__(self, days=7, order_by=""): if not days: days = 7 from_time = DateTime.today()-(int(days)*DateTime.oneDay) from_time = from_time.strftime("%Y-%m-%d") self.where = ["end_time > '%s'" % from_time] if not order_by: order_by = "arp.ip,arp.mac,cam.sysname,module,port,start_time" self.order_by = order_by self.select = "" def sql(self): where = " AND ".join(self.where) return """%s WHERE %s ORDER BY %s""" % (self.select, where, self.order_by) def execute(self): sql = self.sql() if apache: logger.debug("Executing SQL query: %s", sql) database.execute(sql) self.result = database.fetchall() if self.result and apache: logger.debug("Query returned %d results", len(self.result)) return self.result def getRows(self, dns=False, active=False, nonActive=False): yield None def getTable(self, dns=False, active=False, nonActive=False): if not active and not nonActive: active = True newresult = [] self.execute() return [row for row in self.getRows(dns, active, nonActive)] def loadTable(self, dns=False, active=False, nonActive=False): self.table = self.getTable(dns, active, nonActive)class ResultRow: def __init__(self, ipaddr, mac, switch, module, port, start_time, end_time, dns=False): self.ipaddr = ipaddr self.mac = mac self.switch = switch self.module = module self.port = port if start_time is not None: self.start_time = start_time.strftime("%Y-%m-%d %H:%M") else: self.start_time = None if end_time is not None: if end_time.year > DateTime.now().year + 1: self.end_time = "Still active" else: self.end_time = end_time.strftime("%Y-%m-%d %H:%M") else: self.end_time = None if dns: self.dnsname = hostname(ipaddr) else: self.dnsname = ""class MACSQLQuery(MachineTrackerSQLQuery): def __init__(self,mac=None,days=7): MachineTrackerSQLQuery.__init__(self, days) self.select = ("SELECT mac, sysname, module, port, start_time, " + "end_time FROM cam") if mac: mac = re.sub("[^0-9a-fA-F%*]+","",mac) mac = mac.lower() if mac.startswith("*") or mac.endswith("*"): self.where.append("mac ILIKE '%s'" % mac.replace("*","%")) else: self.where.append("mac = '%s'" % mac) self.order_by = "mac,sysname,module,port,start_time DESC" def getRows(self, dns=False, active=False, nonActive=False): lastKey = None for row in self.result: mac, switch, module, port, start, end = row key = (mac, switch, module, port) if key == lastKey: yield ResultRow(None, None, None, None, None, start, end, False) else: lastKey = key yield ResultRow(None, mac, switch, module, port, start, end, False)class IPSQLQuery(MachineTrackerSQLQuery): def __init__(self, ip_from=None, ip_to=None, days=7, macTracker=None): MachineTrackerSQLQuery.__init__(self, days) self.select = ("SELECT ip, mac, start_time AS start, " + "end_time AS end FROM arp") if not macTracker: self.ip_from = ip_from self.ip_to = ip_to self.where.append("ip BETWEEN '%s' AND '%s'" % (ip_from,ip_to)) self.order_by = "ip,mac,start_time DESC" else: # Perform a search for MAC addresses in the arp table, # instead of the typical IP search. This hack uses the # mac limitation from the WHERE clause of a MACSQLQuery. self.macTracker = macTracker self.where.append(macTracker.where[-1]) self.order_by = "mac,ip,start_time DESC" # Replace the "advanced" IP table generator for a simpler # one when searching for a MAC address self.getRows = self.getRowsMac def getRowsMac(self, dns=False, active=False, nonActive=False): lastKey = None for row in self.result: ipaddr, mac, start, end = row key = (ipaddr, mac) if key == lastKey: yield ResultRow(None, None, None, None, None, start, end, dns) else: lastKey = key yield ResultRow(ipaddr, mac, None, None, None, start, end, dns) def getRows(self, dns=False, active=False, nonActive=False): currentRow = 0 # Counts current row in SQL result set firstIP = self.ip_from lastIP = self.ip_to ipCounter = self.ip_from lastKey = None while ipCounter <= lastIP: isActive = False while True: try: ipaddr, mac, start, end = self.result[currentRow] key = (ipaddr, mac) except IndexError: break if IPy.IP(ipaddr) == ipCounter: isActive = True currentRow += 1 if active: if key == lastKey: yield ResultRow(None, None, None, None, None, start, end, dns) else: lastKey = key yield ResultRow(ipaddr, mac, None, None, None, start, end, dns) else: break if nonActive and not isActive: yield ResultRow(ipCounter, None, None, None, None, None, None, dns) ipCounter = IPy.IP(ipCounter.ip + 1) class SwPortSQLQuery(MACSQLQuery): def __init__(self, ip, module, port, days=7): MACSQLQuery.__init__(self, mac=None, days=days) self.order_by = "sysname, module, port, mac, start_time DESC" self.where.append("sysname ILIKE '%s%%'" % ip) if module and module != "*": self.where.append("module = '%s'" % module) if port and port != "*": self.where.append("port = '%s'" % port)class MachineTrackerForm: def __init__(self,days="",dns="",active="",nonActive=""): offon = ['off', 'on'] self.dns = offon[bool(dns)] self.days = days if not active and not nonActive: active = True self.aip = offon[bool(active)] self.naip = offon[bool(nonActive)] self.search = ""class IPForm (MachineTrackerForm): def __init__(self,ip_from,ip_to,days,dns,active,nonActive): MachineTrackerForm.__init__(self,days,dns,active,nonActive) self.ip_from = ip_from self.ip_to = ip_to self.search = "ip"class MACForm (MachineTrackerForm): def __init__(self,mac,days,dns,active,nonActive): MachineTrackerForm.__init__(self,days,dns,active,nonActive) self.mac = mac self.search = "mac"class SwPortForm (MachineTrackerForm): def __init__(self, switch, module="*", port="*", days="", dns="", active="", nonActive=""): MachineTrackerForm.__init__(self,days,dns,active,nonActive) self.switch = switch self.module = module self.port = port self.search = "swp" def hostname(ip): """Perform a reverse DNS lookup for ip. Uses an internal cache to speed up results when the same ip is lookup up several times during one session. """ if ip is None: return None if ip not in hostCache: try: hostCache[ip] = gethostbyaddr(str(ip))[0] except herror: hostCache[ip] = "--" return hostCache[ip]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -