Example #1
0
class cmdOSPF(cmd.Cmd):
    """Simple command processor for OSPF."""
    def cmdloop(self, routerID, routerDeadInterval, RouterPriority,
                hellointerval, inttransDelay):
        self.HelloInterval = hellointerval
        self.RouterID = routerID
        self.RouterDeadInterval = routerDeadInterval
        self.RouterPriority = RouterPriority
        self.IntTransDelay = inttransDelay

        self.listInterfaces = []
        self.dataforUnicastDB = {}
        self.StartInterfacesList()
        self.LSDB = {}
        self.OpaqueID = 0
        self.fakeRoutingTable = RoutingTable(self)
        self.realRoutingTable = ABRRoutingTable(self)

        self.thread = threading.Thread(target=self.multicastReceiver, args=())
        self.thread.daemon = True
        self.thread.start()

        self.threadInc = threading.Thread(target=self.incrementLSATimer,
                                          args=())
        self.threadInc.daemon = True
        self.threadInc.start()

        self.threadABR = False
        self.ABR = False

        self.threadUnicast = {}
        return cmd.Cmd.cmdloop(self)

    def do_hello(self, line):
        """ Hello!!!"""
        print "hello!"

    def do_kernel_forwarding_table(self, line):
        """shows the kernel forwarding table"""
        bashCommand = "route -n"
        os.system(bashCommand)

    def do_ping(self, line):
        """ping [ip address]: Ping linux command. Only send 2 echo requests"""
        bashCommand = "ping -c 2 " + line
        os.system(bashCommand)

    def do_EOF(self, line):
        """to stop reading a file"""
        return True

    def do_bye(self, line):
        """to stop and exit the program"""
        print "Bye!"
        self.realRoutingTable.RemoveEntriesonKernelRT()
        return True

    def do_lsdb(self, line):
        """lsdb [area ip]: list all LSAs of the area"""

        self.LSDB[line][0].printLSDB()

    def do_graph(self, line):
        """graph [area ip]: shows the graph of the area"""
        self.LSDB[line][0].printGraph()

    def do_list(self, line):
        """list the interfaces of the equipment"""
        print utils.getAllInterfaces()

    def do_area_forwarding_table(self, line):
        """shows the area forwarding table based ony on the network and router LSAs for intra-area routing"""
        self.fakeRoutingTable.printAll()

    def do_forwarding_table(self, line):
        """shows the forwarding table of the OSPF"""
        self.realRoutingTable.printAll()

    def do_interface(self, line):
        """interface [name interface] [area] [cost]: to add a new interface on the program"""
        print "Add interface to OSPF"
        inter, area, cost = line.split()

        cost = int(cost)
        intadd = utils.getIPofInterface(inter)
        type = utils.getTypeofInterface(inter)
        netmask = utils.getNetMaskofInterface(inter)

        self.setInterface(
            interface(type, intadd, netmask, area, self.HelloInterval,
                      self.RouterDeadInterval, self.IntTransDelay,
                      self.RouterPriority, self.RouterID, self, cost), inter,
            self.RouterID, area)

    def multicastReceiver(self):
        MCAST_GROUP = '224.0.0.5'
        PROTO = 89

        cast = mcast.mcast()
        mgroup = cast.create(MCAST_GROUP, PROTO)
        while True:
            data, addr = cast.recv(mgroup)
            interface_name = self.WhatInterfaceReceivedthePacket(addr[0])
            packet = mcast.readPack(addr, data)
            interface_obj = self.getInterfaceByName(interface_name)
            if interface_name == 0 or interface_obj == None or packet == 0:
                continue
            interface_obj.packetReceived(packet, True)

    def unicastReceiver(self, interfaceaddr, type, timeout):
        PROTO = 89
        bufferSize = 1500

        s = socket(AF_INET, SOCK_RAW, PROTO)
        s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        s.bind((interfaceaddr, PROTO))
        if timeout:
            s.settimeout(20.0)
        try:
            while True:
                data, addr = s.recvfrom(bufferSize)
                packet = mcast.readPack(addr, data)
                if packet.getType() == type:
                    if type == 2:
                        self.dataforUnicastDB[interfaceaddr].receivePacket(
                            packet)
                    else:
                        return packet
        except Exception:
            return 0

    def getNextDBPacket(self, ip):
        return self.dataforUnicastDB[ip].returnpacket()

    def StartInterfacesList(self):
        for x in utils.getAllInterfaces():
            self.listInterfaces.append({
                'interface-name':
                x,
                'ip':
                utils.getIPofInterface(x),
                'netmask':
                utils.getNetMaskofInterface(x),
                'interface-object':
                None
            })
            self.dataforUnicastDB[utils.getIPofInterface(
                x)] = DataStructurePacketsUnicast()

    def setInterface(self, object_interface, interface_name, rid, area):
        for x in self.listInterfaces:
            if x['interface-name'] == interface_name:
                x['interface-object'] = object_interface
                x['interface-area'] = area

        self.createLSA(area, rid, False)

    def createLSA(self, area, rid, sn):
        # create/Update RouterLSA
        linkdata = []
        for x in self.listInterfaces:
            if x['interface-object'] != None and x['interface-object'].getArea(
            ) == area:
                typeLink = x['interface-object'].getTypeLink()
                if typeLink == 2:  # transit network
                    linkdata.append([
                        x['interface-object'].getDR(),
                        x['interface-object'].getIPIntAddr(), typeLink, 0,
                        x['interface-object'].getMetric()
                    ])
                else:
                    if typeLink == 3:  # stub
                        networkIP = utils.getNetworkIP(
                            x['interface-object'].getIPIntAddr(),
                            x['interface-object'].getIPInterfaceMask())
                        linkdata.append([
                            networkIP,
                            x['interface-object'].getIPInterfaceMask(),
                            typeLink, 0, x['interface-object'].getMetric()
                        ])
                    else:
                        "Error creating LSA. Link Type not supported"
        if sn == False:
            rlsa = RouterLSA(None, 0, 0, 1, rid, rid, 0, 1, 0, 0, 0, False,
                             len(linkdata), linkdata)
        else:
            rlsa = RouterLSA(None, 0, 0, 1, rid, rid, sn, 1, 0, 0, 0, False,
                             len(linkdata), linkdata)

        aux = 1
        if area in self.LSDB:

            if 'ABR' in self.LSDB:
                aux = aux + 1
            if len(self.LSDB) > aux:
                rlsa.setBbit(True)
                if self.ABR == False:
                    self.updateOurRouterLSAsTOABR(area)
                if self.threadABR == True:
                    self.threadforAbrLsdbStart()
        else:
            if area != 'ABR':
                x = [LSDB(area, self), 0]
            else:
                x = [ABRLSDB(area, self), 0]
                aux = aux + 1
            self.LSDB[area] = x
            if len(self.LSDB) > aux:
                rlsa.setBbit(True)
                if self.ABR == False:
                    self.updateOurRouterLSAsTOABR(area)
                if self.threadABR == False:
                    self.threadforAbrLsdbStart()

        self.LSDB[area][0].receiveLSA(rlsa)

    def updateOurRouterLSAsTOABR(self, area):
        self.ABR = True
        for x in self.LSDB:
            if x == 'ABR' or x == area:
                continue
            self.createLSA(x, self.RouterID, False)

    def threadforAbrLsdbStart(self):
        self.threadABR = True
        t = threading.Thread(target=self.createLSDBforABROverlay, args=[True])
        t.daemon = True
        t.start()

    def newABRNeighbord(self):
        if self.ABR:
            self.createABRLSA()

    def createLSDBforABROverlay(self, createLSAs):
        if 'ABR' not in self.LSDB:
            x = [ABRLSDB('ABR', self), 0]
            self.LSDB['ABR'] = x
        if createLSAs:
            self.createABRLSA()
            self.createPrefixLSAs()
            self.createASBRLSAs()

    def createABRLSA(self):
        # create ABR LSA
        opaqueID = self.getOpaqueID()
        lsa = ABRLSA(None, 0, 2, opaqueID, self.RouterID, 0, 0, 0)

        # get ABR Neigbords and metric
        ABRNeighbords = []
        for x in self.LSDB:
            if x == 'ABR':
                continue
            N = self.LSDB[x][0].getNeighbordABR(self.RouterID)
            for y in N:
                ABRNeighbords.append(y)

        # add them
        for x in ABRNeighbords:
            lsa.addLinkDataEntry(x)
        # add LSA to LSDB
        self.LSDB['ABR'][0].receiveLSA(lsa)

    def createPrefixLSAs(self):
        self.fakeRoutingTable.createPrefixLSAs()

    def createASBRLSAs(self):
        # Get ASBRs Routers
        for x in self.LSDB:
            if x == 'ABR':  # special LSDB
                continue
            for y in self.LSDB[x][0].getAsbrRouterLSAS(self.RouterID):
                # create PrefixLSA for every NetworkLSA
                opaqueID = self.getOpaqueID()
                data = y.getPrefixAndCost()
                lsa = ASBRLSA(None, 0, 2, opaqueID, self.RouterID, 0, 0, 0,
                              data[0], data[1])
                self.LSDB['ABR'][0].receiveLSA(lsa)

    def getActiveAreas(self):
        out = []
        for x in self.LSDB:
            if x == 'ABR':  # special LSDB
                continue
            out.append(x)
        return out

    def getOpaqueID(self):
        self.OpaqueID += 1
        return self.OpaqueID

    def incrementLSATimer(self):
        while True:
            for x in self.LSDB:
                if self.LSDB[x][1] == 1800:
                    area = self.LSDB[x][0].getArea()
                    if area != 'ABR':
                        self.createLSA(area, self.RouterID, False)
                    else:
                        self.createABRLSA()
                    self.LSDB[x][1] = 0
                else:
                    self.LSDB[x][1] = self.LSDB[x][1] + 1
            sleep(1)

    def WhatInterfaceReceivedthePacket(self, sourceIP):
        for x in range(len(self.listInterfaces)):
            if utils.IPinNetwork(sourceIP, self.listInterfaces[x]['ip'],
                                 self.listInterfaces[x]['netmask']):
                return self.listInterfaces[x]['interface-name']
        return 0

    def getInterfaceByName(self, interface_name):
        for x in range(len(self.listInterfaces)):
            if self.listInterfaces[x]['interface-name'] == interface_name:
                return self.listInterfaces[x]['interface-object']
        return 0  # error

    def receiveLSAtoLSDB(self, lsa, area):
        if area not in self.LSDB:
            if area == 'ABR':
                self.createLSDBforABROverlay(False)

        self.LSDB[area][0].receiveLSA(lsa)

    def getLSDB(self, areaid):
        return self.LSDB[areaid][0]

    def getInterfaceIPExcept(self, area):
        out = []
        for x in self.listInterfaces:
            if x['interface-object'] != None and x['interface-area'] == area:
                out.append(x['interface-object'].getIPIntAddr())
        return out

    def getAllInterface(self):
        out = []
        for x in self.listInterfaces:
            if x['interface-object'] != None:
                out.append(x['interface-object'].getIPIntAddr())
        return out

    def getRouterID(self):
        return self.RouterID

    def receivenewLSA(self, lsa):
        if 'ABR' in self.LSDB:
            self.receiveLSAtoLSDB(lsa, 'ABR')

    def setNewRoutes(self, routes, whatRT):
        if whatRT:
            self.realRoutingTable.receiveEntries(routes)
        else:
            self.fakeRoutingTable.receiveEntries(routes)

    def createPrefixLSA(self, prefix, cost, netmask):
        opaqueID = self.getOpaqueID()
        lsa = PrefixLSA(None, 0, 2, opaqueID, self.RouterID, 0, 0, 0, cost,
                        netmask, prefix)
        if 'ABR' in self.LSDB:
            self.LSDB['ABR'][0].receiveLSA(lsa)

    def createSummaryLSAfromPrefixLSA(self, lsid, netmask, metric):
        newLSA = SummaryLSA(None, 0, 2, 3, lsid, self.getRouterID(), 0, 0, 0,
                            netmask, metric)
        for x in self.LSDB:
            if x == 'ABR':
                continue
            self.LSDB[x][0].receiveLSA(newLSA)

    def getRoutingDatatointraareaRouting(self, destination):
        return self.fakeRoutingTable.getdataabout(destination)

    def getbestpathtoABR(self, abr):
        entries = []
        for x in self.LSDB:
            if x == 'ABR':
                continue
            data = self.LSDB[x][0].getPathtoDestination(abr)
            if data is not False:
                entries.append(data)
        if len(entries) > 0:
            routes = []
            entries = sorted(entries, key=itemgetter('cost'))
            leastcost = entries[0]['cost']
            routes.append(entries[0])
            for z in range(1, len(entries) - 1):
                if entries[z]['cost'] != leastcost:
                    break
                routes.append(entries[z])
            return routes
        else:
            return False

    def startThreadUnicast(self, interface):
        if interface in self.threadUnicast:
            return
        else:
            self.threadUnicast[interface] = threading.Thread(
                target=self.allwaysUnicast, args=[interface])
            self.threadUnicast[interface].daemon = True
            self.threadUnicast[interface].start()

    def allwaysUnicast(self, interface):
        PROTO = 89
        bufferSize = 1500

        s = socket(AF_INET, SOCK_RAW, PROTO)
        s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        while True:
            s.bind((interface, PROTO))
            try:
                data, addr = s.recvfrom(bufferSize)
                packet = mcast.readPack(addr, data)
                interfaceName = utils.getInterfaceByIP(interface)
                interface_obj = self.getInterfaceByName(interfaceName)
                if interface == 0 or interface_obj == None or packet == 0:
                    continue
                interface_obj.packetReceived(packet, False)
            except Exception:
                continue

    def AlertToCreateNetworkLSA(self, lsid, sn):
        interface = self.WhatInterfaceReceivedthePacket(lsid)
        interface_obj = self.getInterfaceByName(interface)
        if interface_obj.havetoNLSA():
            interface_obj.createNLSA(sn, False)
        else:
            interface_obj.createNLSA(sn, True)