📄 l2trace.py
字号:
## $Id: machinetracker.py 3106 2005-01-20 10:47:13Z mortenv $## Copyright 2003, 2004 Norwegian University of Science and Technology## 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: Kristian Eide <kreide@gmail.com>#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.l2traceTemplate import l2traceTemplateconnection = db.getConnection('webfront', 'manage')database = connection.cursor()def isGw(netboxid): if netboxid not in gwCache: isGw = False try: database.execute("SELECT netboxid FROM netbox WHERE netboxid="+`netboxid`+" AND catid IN ('GW','GSW')") d = database.fetchall() isGw = len(d) > 0 except: pass gwCache[netboxid] = isGw return gwCache[netboxid]def getIpSysname(netboxid): database.execute("SELECT ip, sysname FROM netbox WHERE netboxid="+`netboxid`) d = database.fetchall() return d[0][0], d[0][1]def getNetboxidVlan(sysname): database.execute("SELECT netboxid, vlan.vlan, swport.swportid FROM netbox JOIN prefix USING(prefixid) JOIN vlan USING(vlanid) LEFT JOIN module USING(netboxid) LEFT JOIN swport USING(moduleid) LEFT JOIN swportvlan ON (swport.swportid=swportvlan.swportid AND direction='o') WHERE sysname LIKE '%"+sysname+"%' OR ip::varchar LIKE '%"+sysname+"%' ORDER BY length(sysname) LIMIT 1") d = database.fetchall() if len(d) > 0: baseNetboxid = None baseVlan = None mp = MP() # Special case for netboxes without uplink (servers) netboxid = d[0][0] vlan = d[0][1] if not d[0][2]: database.execute("SELECT netboxid, vlan.vlan, ifindex, module, port FROM swport JOIN module USING(moduleid) JOIN netbox USING(netboxid) JOIN swportvlan USING(swportid) JOIN vlan USING(vlanid) WHERE to_netboxid='"+str(netboxid)+"' LIMIT 1") d = database.fetchall() if len(d) > 0: baseNetboxid = netboxid baseVlan = vlan netboxid = d[0][0] vlan = d[0][1] mp = MP(d[0][2], d[0][3], d[0][4]) return netboxid, vlan, baseNetboxid, baseVlan, mp # Try to lookup vlan for host vlan = '' ip = lookupIp(sysname) if ip: database.execute("SELECT vlan FROM prefix JOIN vlan USING(vlanid) WHERE '"+ip+"' << netaddr") d = database.fetchall() if len(d) > 0: vlan = d[0][0] return None, vlan, None, None, MP()def getBoxForHost(ip): # Find match in arp/cam try: database.execute("select cam.netboxid,cam.ifindex,module.module,swport.port,vlan.vlan from arp join cam using(mac) join swport on (moduleid in (select moduleid from module where module.netboxid=cam.netboxid) and swport.ifindex=cam.ifindex) JOIN module USING(moduleid) join swportvlan using(swportid) join vlan using(vlanid) where ip='" + ip + "' and cam.end_time='infinity' and arp.end_time='infinity' LIMIT 1") d = database.fetchall() if len(d) > 0: return d[0][0], MP(d[0][1], d[0][2], d[0][3]), d[0][4] except: pass return None, None, Nonedef getPathToGw(netboxid, mpIn, vlan, trunk, gwId, path): if trunk: vlanS = 'trunk' else: vlanS = vlan #if isGw(netboxid): if netboxid == gwId: path.append([netboxid, vlanS, mpIn, MP(), 2]) return True # Fetch uplink database.execute("SELECT a.to_netboxid, a.ifindex, moda.module, a.port, a.trunk, b.ifindex AS to_ifindex, modb.module AS to_module, b.port AS to_port FROM module moda JOIN swport a USING(moduleid) JOIN swportvlan USING (swportid) JOIN vlan USING(vlanid) JOIN swport b ON (a.to_swportid = b.swportid) JOIN module modb ON (b.moduleid=modb.moduleid) WHERE moda.netboxid="+`netboxid`+" AND vlan.vlan="+`vlan`+" AND direction='o' LIMIT 1") d = database.fetchall() if len(d) == 0: #print "Error, " + getSysname(netboxid) + "("+`netboxid`+") has no uplink on vlan " + `vlan` + ", aborting." path.append([netboxid, vlanS, mpIn, MP(), 2]) return False if d[0][4] == 1: trunk = True else: trunk = False mpOut = MP(d[0][1], d[0][2], d[0][3]) path.append([netboxid, vlanS, mpIn, mpOut, 2]) mpNextIn = MP(d[0][5], d[0][6], d[0][7]) return getPathToGw(d[0][0], mpNextIn, vlan, trunk, gwId, path)def getPath(host): path = [] id, vlan, baseNetboxid, baseVlan, mpOut = getNetboxidVlan(host) if baseNetboxid: path.append([baseNetboxid, baseVlan, MP(), MP(), 2]) ip = host if not id: ip = lookupIp(host) if ip: path.append([ip, vlan]) id, mpOut, vlan = getBoxForHost(ip) else: path.append([host, vlan]) foundGw = False if id: # Find correct netboxid for GW database.execute("SELECT module.netboxid FROM vlan JOIN prefix USING(vlanid) JOIN gwportprefix ON (prefix.prefixid = gwportprefix.prefixid AND (hsrp='t' OR gwip::text IN (SELECT MIN(gwip::text) FROM gwportprefix GROUP BY prefixid HAVING COUNT(DISTINCT hsrp) = 1))) JOIN gwport USING(gwportid) JOIN module USING(moduleid) WHERE vlan=" + str(vlan)); d = database.fetchall() gwId = None if len(d) > 0: gwId = d[0][0] foundGw = getPathToGw(id, mpOut, vlan, False, gwId, path) if not foundGw: path.append(['Path to router not found', 'error']) # Didn't find GW, look up gw for this vlan d = [] try: database.execute("SELECT netboxid, vlan FROM netbox JOIN module USING(netboxid) JOIN gwport USING(moduleid) JOIN gwportprefix USING(gwportid) JOIN prefix ON (gwportprefix.prefixid=prefix.prefixid) JOIN vlan USING(vlanid) WHERE '"+ip+"' << netaddr ORDER BY gwip") d = database.fetchall() except: pass if len(d) > 0: path.append([d[0][0], str(d[0][1]), MP(), MP(), 2]) else: path.append(['Host not active', 'error']) return pathdef handler(req): global hostCache hostCache = {} global gwCache gwCache = {} global ipCache ipCache = {} args = URI(req.unparsed_uri) page = l2traceTemplate() page.l2tracer = None page.form = l2traceForm(args.get("host_from"), args.get("host_to")) if args.get("host_from") or args.get("host_to"): page.l2tracer = l2traceQuery(args.get("host_from"), args.get("host_to")) page.l2tracer.loadTable() req.content_type = "text/html" req.send_http_header() req.write(page.respond()) return apache.OKclass MP: def __init__(self, ifindex='', module='', port=''): self.ifindex = ifindex self.module = module self.port = portclass ResultRow: def __init__(self, idx, level=2, netboxid=None, ipaddr='', sysname='', mpIn=MP(), mpOut=MP(), vlan=''): self.netboxid = netboxid self.ipaddr = ipaddr self.sysname = sysname self.mpIn = mpIn self.mpOut = mpOut self.vlan = vlan if level == 2: self.level = 'L2' else: self.level = 'L3' self.idx = idx self.hostOk = True if self.vlan == 'error': self.level = '' self.vlan = '' self.hostOk = False self.ifindexIn = mpIn.ifindex self.ifindexOut = mpOut.ifindex self.portIn = str(mpIn.module) if mpIn.port: self.portIn += '/' + str(mpIn.port) self.portOut = str(mpOut.module) if mpOut.port: self.portOut += '/' + str(mpOut.port)class l2traceQuery: row_idx=0 def __init__(self, host_from, host_to): self.host_from = host_from self.host_to = host_to def reverse_path_list(self, path): path.reverse() for x in path: if len(x) > 2: t = x[2] x[2] = x[3] x[3] = t return path def trace(self): self.path = [] if self.host_from: self.path = getPath(self.host_from) if self.host_to: self.path.append(-1) to_path = None if self.host_to: to_path = getPath(self.host_to) # Check if hosts are on the same vlan if self.host_from and self.host_to: ip_from = lookupIp(self.host_from) ip_to = lookupIp(self.host_to) if ip_from and ip_to: database.execute("SELECT COUNT(prefixid) FROM prefix WHERE '"+ip_from+"' << netaddr OR '"+ip_to+"' << netaddr GROUP BY prefixid") d = database.fetchall() if d[0][0] == 1: # Same vlan, find first matching box in both lists and remove everything above l1 = [] break_outer = False for b1 in self.path: if b1 == -1: break l1.append(b1) l2 = [] for b2 in to_path: if b1[0] == b2[0] and b1[1]!='error': # Same box if len(b1) >= 4 and len(b2) >= 3: b1[3] = b2[2] # Connect up the ports for x in self.reverse_path_list(l2): l1.append(x) to_path = None self.path = l1 break_outer = True break l2.append(b2) if break_outer: break if to_path: for x in self.reverse_path_list(to_path): self.path.append(x) def getRows(self): for row in self.path: self.row_idx += 1 if row == -1: yield ResultRow(self.row_idx, 3) elif len(row) == 2: yield ResultRow(self.row_idx, 2, None, row[0], hostname(row[0]), MP(), MP(), row[1]) else: netboxid, vlan, mpIn, mpOut, level = row ip, sysname = getIpSysname(netboxid) yield ResultRow(self.row_idx, level, netboxid, ip, sysname, mpIn, mpOut, vlan) def getTable(self): self.trace() return [row for row in self.getRows()] def loadTable(self): self.table = self.getTable()class l2traceForm: def __init__(self,host_from, host_to): self.host_from = host_from self.host_to = host_todef lookupIp(host): if host is None: return None if host not in ipCache: try: ipCache[host] = gethostbyname(host) except: ipCache[host] = None return ipCache[host]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(ip)[0] except: hostCache[ip] = '' return hostCache[ip]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -