⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 l2trace.py

📁 监控大型网络的软件。能够自动发现拓扑结构
💻 PY
字号:
#! /usr/bin/env python# $Id: machinetracker.py 3106 2005-01-20 10:47:13Z mortenv $## Copyright 2003, 2004 Norwegian University of Science and Technology# Copyright 2007 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: Kristian Eide <kreide@gmail.com>#          Stein Magnus Jodal <stein.magnus.jodal@uninett.no>#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 l2traceTemplatedef isGw(netboxid):    if netboxid not in gwCache:        isGw = False        try:            database.execute("SELECT netboxid FROM netbox WHERE netboxid=%s AND catid IN ('GW','GSW')", (netboxid,))            d = database.dictfetchall()            isGw = len(d) > 0        except db.driver.ProgrammingError:            connection.rollback()        gwCache[netboxid] = isGw    return gwCache[netboxid]def getIpSysname(netboxid):    database.execute("SELECT ip, sysname FROM netbox WHERE netboxid=%s", (netboxid,))    r = database.dictfetchall()[0]    return r['ip'], r['sysname']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 %s OR ip::varchar LIKE %s ORDER BY length(sysname) LIMIT 1", ("%"+sysname+"%",)*2)    d = database.dictfetchall()    if len(d) > 0:        baseNetboxid = None        baseVlan = None        mp = MP()        # Special case for netboxes without uplink (servers)        r = d[0]        netboxid = r['netboxid']        vlan = r['vlan']        if not r['swportid']:            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=%s LIMIT 1", (netboxid,))            d = database.dictfetchall()            if len(d) > 0:                r = d[0]                baseNetboxid = netboxid                baseVlan = vlan                netboxid = r['netboxid']                vlan = r['vlan']                mp = MP(r['ifindex'], r['module'], r['port'], r['interface'])        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 %s << netaddr", (ip,))        d = database.dictfetchall()        if len(d) > 0:            vlan = d[0]['vlan']    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,swport.interface,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=%s and cam.end_time='infinity' and arp.end_time='infinity' LIMIT 1", (ip,))        d = database.dictfetchall()        if len(d) > 0:            r = d[0]            return r['netboxid'], MP(r['ifindex'], r['module'], r['port'],                                     r['interface']), r['vlan']    except db.driver.ProgrammingError:        connection.rollback()    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.interface, a.trunk, b.ifindex AS to_ifindex, modb.module AS to_module, b.port AS to_port, b.interface AS to_interface 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=%s AND vlan.vlan=%s AND direction='o' LIMIT 1", (netboxid, vlan))    d = database.dictfetchall()    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    r = d[0]    if r['trunk'] == 1:        trunk = True    else:        trunk = False    mpOut = MP(r['ifindex'], r['module'], r['port'], r['interface'])    path.append([netboxid, vlanS, mpIn, mpOut, 2])    mpNextIn = MP(r['to_ifindex'], r['to_module'], r['to_port'],                  r['to_interface'])    return getPathToGw(r['to_netboxid'], 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=%s", (vlan,))        d = database.dictfetchall()        gwId = None        if len(d) > 0:            gwId = d[0]['netboxid']        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 %s << netaddr ORDER BY gwip", (ip,))            d = database.dictfetchall()        except db.driver.ProgrammingError:            connection.rollback()        if len(d) > 0:            path.append([d[0]['netboxid'], str(d[0]['vlan']), MP(), MP(), 2])        else:            path.append(['Host not active', 'error'])    return pathdef handler(req):    global hostCache    hostCache = {}    global gwCache    gwCache = {}    global ipCache    ipCache = {}    global connection    connection = db.getConnection('webfront', 'manage')    global database    database = connection.cursor()    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='', interface=''):        self.ifindex = ifindex        self.module = module        self.port = port        self.interface = interfaceclass 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.interface or mpIn.port:            self.portIn += '/' + str(mpIn.interface or mpIn.port)        self.portOut = str(mpOut.module)        if mpOut.interface or mpOut.port:            self.portOut += '/' + str(mpIn.interface or 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 %s << netaddr OR %s << netaddr GROUP BY prefixid", (ip_from, ip_to))                r = database.dictfetchall()[0]                if r['count'] == 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 + -