INET Framework for OMNeT++/OMNEST
RIPRouting.cc
Go to the documentation of this file.
00001 
00020 #include "RIPRouting.h"
00021 #include "IPRoute.h"
00022 #include <vector>
00023 
00024 #ifndef WITHOUT_IPv4
00025 #include "IPv4InterfaceData.h"
00026 #endif
00027 
00028 #define BROADCAST "255.255.255.255" 
00030 using namespace std;
00031 
00032 Define_Module(RIPRouting);
00033 
00035 std::ostream& operator<<(std::ostream& os, const RIPinterface& e)
00036 {
00037     os << "ID = " << e.intID << "; addr = " << e.addr << "; mask = " << e.mask << "; pass = " << e.passive << "; broad = " << e.broadcast;
00038     return os;
00039 };
00040 
00042 std::ostream& operator<<(std::ostream& os, const RIPRouteTimer& e)
00043 {
00044          if (e.timer == NULL)
00045                  os << "Adresa= " << e.route->getHost() << "; NIC ";
00046          else
00047                  os << "Adresa= " << e.route->getHost() << "; " << e.timer->getFullName() << "  ArrivalTime: " << e.timer->getArrivalTime();
00048     return os;
00049 };
00050 
00052 std::ostream& operator<<(std::ostream& os, const RIPRedistribution& e)
00053 {
00054          if (e.redistrinute)
00055                  os << "Redistribuce: YES; Protokol: " << e.protocol << "; Metrika: " << e.metric;
00056          else
00057                  os << "Redistribuce: NO; Protokol: " << e.protocol << "; Metrika: " << e.metric;
00058     return os;
00059 };
00060 
00062 RIPRouting::~RIPRouting()
00063 {
00064         for (int i = 0; i < (int) routeTimer.size(); i++)
00065         {
00066                 if (routeTimer[i].timer != NULL)
00067                 {
00068                         if (routeTimer[i].timer->isScheduled())
00069                                 cancelEvent(routeTimer[i].timer);
00070                         delete routeTimer[i].timer;
00071                 }
00072         }
00073         if (triggerTimer != NULL)
00074         {
00075                 if (triggerTimer->isScheduled())
00076                         cancelEvent(triggerTimer);
00077                 delete triggerTimer;
00078         }
00079 }
00080 
00088 IPAddress getMask(IPAddress addr)
00089 {
00090         IPAddress mask;
00091         if (addr< "126.255.255.255")
00092                 mask = "255.0.0.0";                     // A
00093         else if (addr < "191.255.255.255")
00094                 mask = "255.255.0.0";           // B
00095         else
00096                 mask = "255.255.255.0";         // C
00097         return mask;
00098 }
00099 
00106 void RIPRouting::insertIft(InterfaceEntry * entryIFT)
00107 {
00108         RIPinterface newIftEntry;
00109 
00110         newIftEntry.intID = entryIFT->getInterfaceId();
00111 
00112         if (entryIFT->isBroadcast())
00113                 newIftEntry.broadcast = true;
00114         else
00115                 newIftEntry.broadcast = false;
00116 
00117         if (entryIFT->isLoopback())
00118                 newIftEntry.loopback = true;
00119         else
00120                 newIftEntry.loopback = false;
00121 
00122         IPv4InterfaceData *ipv4 = entryIFT->ipv4Data();
00123         IPAddress IPaddr = ipv4->getIPAddress();
00124         newIftEntry.addr = IPvXAddress(IPaddr);
00125         newIftEntry.mask = ipv4->getNetmask();
00126         newIftEntry.passive = false;
00127         newIftEntry.entry = entryIFT;
00128         ripIft.push_back(newIftEntry);
00129 }
00130 
00137 void RIPRouting::sendTrigger()
00138 {
00139         if (triggerTimer != NULL)
00140         {
00141                 if (triggerTimer->isScheduled())
00142                         cancelEvent(triggerTimer);
00143                 delete triggerTimer;
00144         }
00145         // vysli trigger zpravu
00146         RIPTimer* newTimer = new RIPTimer("Trigger");
00147         newTimer->setTimerKind(trigger);
00148         triggerTimer = newTimer;
00149         scheduleAt(simTime() + exponential(3), newTimer);
00150 }
00151 
00161 int RIPRouting::getRouteRT (RIPTimer *timer)
00162 {
00163         for (int i = 0; i < (int)routeTimer.size(); i++)
00164         {
00165                 if (routeTimer[i].timer == timer)
00166                 {
00167                         return i;
00168                 }
00169         }
00170         return -1;
00171 }
00172 
00182 int RIPRouting::getTimerRT (IPRoute *route)
00183 {
00184         for(int i = 0; i < (int) routeTimer.size(); i++)
00185         {
00186                 if (routeTimer[i].route == route)
00187                 {
00188                         return i;
00189                 }
00190         }
00191         return -1;
00192 }
00193 
00203 RIPTimer * RIPRouting::updateTimer(int type, RIPRouteTimer * entry)
00204 {
00205         RIPTimer *timer = new RIPTimer();
00206         timer->setTimerKind(type);
00207 
00208         switch(type)
00209         {
00210                 case hello:
00211                         timer->setName("Hello");
00212                         scheduleAt(simTime() + 30.0 + exponential(1), timer);
00213                         break;
00214 
00215                 case timeout:
00216                         timer->setName("Timeout");
00217                         scheduleAt(simTime() + 120.0, timer);
00218                         if (entry != NULL && entry->timer != NULL)
00219                         {
00220                                 cancelEvent(entry->timer);
00221                                 delete entry->timer;
00222                                 entry->timer = timer;
00223                         }
00224                         break;
00225 
00226                 case garbage:
00227                         timer->setName("Garbage");
00228                         scheduleAt(simTime() + 180.0, timer);
00229                         entry->timer = timer;
00230                         break;
00231         }
00232         return timer;
00233 }
00234 
00243 bool RIPRouting::checkTwin(IPRoute * entryRT)
00244 {
00245         bool cont = false;
00246         for (int k = 0; k < (int) routeTwins.size(); k++)
00247         {
00248                 if (entryRT == routeTwins[k].route1 || entryRT == routeTwins[k].route2)
00249                 {
00250                         EV << hostname << ": Takováto dvojice jiz existuje!!!" << endl;
00251                         cont = true;
00252                 }
00253         }
00254         return cont;
00255 }
00256 
00264 void RIPRouting::sendPacket(int command, IPAddress destAddr)
00265 {
00266    EV << "RIPRouting::sendPacket" << endl;
00267    IPvXAddress destXAddr = IPvXAddress(destAddr);
00268    bool right = false;
00269    RIPPacket *msg;
00270 
00271    // posilani broadcast zprav na vsechny vystupni interfacy
00272    if (destAddr == BROADCAST)
00273    {
00274         EV << "Broadcast" << endl;
00275                 for (int i = 0; i < (int)ripIft.size(); i++)
00276                 {
00277                         // kontrola interface, nezasilame na pasivni interfaci, jen na broadcastove
00278                         // if (ripIft[i].passive || !ripIft[i].broadcast)
00279                         if (ripIft[i].passive || ripIft[i].loopback)
00280                         {
00281                                 if (ripIft[i].passive)
00282                                         EV << "FUJ" << endl;
00283                                 else if (ripIft[i].loopback)
00284                                         EV << "FUJ2" << endl;
00285                                 continue;}
00286 
00287                         // posilame jen do siti, ktere jsou definovane v network
00288                         for (int j = 0; j < (int) network.size(); j++)
00289                         {
00290                                 EV << hostname << ": Kontrola na IP interfacu " << ripIft[i].addr.get4() << "s IP adresou v network: " << network[j] << " s maskou: " << getMask(network[j]) << endl;
00291                                 if (IPAddress::maskedAddrAreEqual(network[j], ripIft[i].addr.get4(), getMask(network[j])))
00292                                 {
00293                                         right = true;
00294                                         break;
00295                                 }
00296                                 else
00297                                         right = false;
00298                         }
00299                         // adresa neni v network
00300                         if (right == false)
00301                         { EV << "FUJ2" << endl;
00302                                 continue;}
00303 
00304                         // vytvori novou RIP zpravu
00305                         if ((msg = createPacket(command, ripIft[i].entry)) == NULL)
00306                                 return;
00307 
00308                         // UDP kontrolni informace (porty, IP adresy, interface)
00309                         UDPControlInfo *ctrl = new UDPControlInfo();
00310                         ctrl->setSrcPort(localPort);
00311                         ctrl->setDestAddr(destXAddr);
00312                         ctrl->setDestPort(destPort);
00313                         ctrl->setSrcAddr(ripIft[i].addr);
00314                         ctrl->setInterfaceId(ripIft[i].intID);
00315                         msg->setControlInfo(ctrl);
00316                         send(msg, "udpOut");
00317                         EV << hostname << ": Posilam zpravu Broadcastem se zdrojem: "<< ripIft[i].addr << endl;
00318                 }
00319    }
00320    // posilani aktualizace na konkretni IP adresu (odpoved na Request)
00321    else
00322    {
00323         EV << hostname << ": Posilam zpravu na adresu:" << destAddr << endl;
00324         IPRoute * route = (IPRoute *) rt->findBestMatchingRoute(destAddr);
00325 
00326         // vytvori novou RIP zpravu
00327                 if ((msg = createPacket(command, route->getInterface())) == NULL)
00328                         return;
00329 
00330                 // UDP kontrolni informace (porty, IP adresy, interface)
00331                 UDPControlInfo *ctrl = new UDPControlInfo();
00332                 ctrl->setSrcPort(localPort);
00333                 ctrl->setDestAddr(destXAddr);
00334                 ctrl->setDestPort(destPort);
00335                 ctrl->setInterfaceId(route->getInterface()->getInterfaceId());
00336                 msg->setControlInfo(ctrl);
00337                 send(msg, "udpOut");
00338    }
00339 }
00340 
00349 RIPPacket* RIPRouting::createPacket(int command, InterfaceEntry * entry)
00350 {
00351    RIPPacket *msg = new RIPPacket();            // novy paket
00352    vector<RouteEntry> newEntry;                         // vektor cest
00353    int size;                                                            // mnozstvi cest
00354 
00355    // Request zprava
00356    if (command == Request)
00357    {
00358         msg->setName("RIPRequest");
00359         RouteEntry entry;
00360                 entry.addressID = 0;
00361                 entry.metric = 16;
00362                 newEntry.push_back(entry);
00363    }
00364    // Response zprava
00365    else
00366    {
00367         msg->setName("RIPResponse");
00368         newEntry = fillNetworks(entry);
00369    }
00370 
00371    // kontrola, zda mame co posilat
00372    if (newEntry.size() <= 0)
00373       return NULL;
00374 
00375    msg->setCommand(command);
00376    msg->setKind(UDP_C_DATA);
00377    size = newEntry.size();
00378    msg->setRouteEntryArraySize(size);
00379 
00380    // naplneni zpravy cestami
00381    for(int i = 0; i < size; i++)
00382       msg->setRouteEntry(i, newEntry[i]);
00383 
00384    return msg;
00385 }
00386 
00399 vector<RouteEntry> RIPRouting::fillNetworks(InterfaceEntry * IntEntry)
00400 {
00401         IPRoute *entryRT = new IPRoute();           // routovaci tabulka
00402         RouteEntry entry;                               // nova polozka s adresou
00403         vector<RouteEntry> newEntry;                // vektor zasilanych adres
00404         IPAddress mask;                                                         // sitova maska
00405         int sizeTab = rt->getNumRoutes();                       // velikost routovaci tabulky
00406         int sizeNet = network.size();                           // pocet siti, ktere se maji posilat
00407 
00408 
00409         // ber postupne site z routovaci tabulky
00410         for (int i = 0; i < sizeTab; i++)
00411         {
00412                 // pokud cesta ma jako zdroj RIP (prisla od souseda), pridej ji...
00413                 entryRT = const_cast<IPRoute*>(rt->getRoute(i));
00414                 if (entryRT->getSource() == INET_API IPRoute::RIP)
00415                 {
00416                         // split horizon => neposilame cesty, ktere jsme pres toto roshrani dostali
00417                         if (entryRT->getInterface() == IntEntry)
00418                                 continue;
00419 
00420                         // kontrola na dve stejne cesty
00421                         bool cont = false;
00422                         for (int j = 0; j < (int) routeTwins.size(); j++)
00423                         {
00424                                 if (entryRT == routeTwins[j].route1 || entryRT == routeTwins[j].route2)
00425                                 {
00426                                         if (IntEntry == routeTwins[j].route1->getInterface() || IntEntry == routeTwins[j].route2->getInterface())
00427                                         {
00428                                                 EV << hostname << ": FillNetworks: Jedna se o dvojce, nikam ji nedavej!!!" << endl;
00429                                                 cont = true;
00430                                         }
00431                                 }
00432                         }
00433                         if (cont == true)
00434                                 continue;
00435 
00436                         // pridava RIP cestu
00437                         EV << hostname << ": Posilam podle RIP zaznamu IP: " << entry.ipAddress << endl;
00438                         entry.addressID = 2;
00439                         entry.mustBeZero2 = 0;
00440                         entry.mustBeZero3 = 0;
00441                         entry.mustBeZero4 = 0;
00442                         entry.ipAddress = entryRT->getHost();
00443                         entry.metric = entryRT->getMetric();
00444                         newEntry.push_back(entry);
00445                         continue;
00446                 } // ... konec cest se zdrojem RIP
00447 
00448                 //... a prihod lokalni adresy, ktere jsou nastavene v konfiguraku (network)
00449                 // ber postupne site nastavene v network a porovnavej ji s cestou z routovaci tabulky
00450                 if (entryRT->getSource() == INET_API IPRoute::IFACENETMASK)
00451                 {
00452                         for (int j = 0; j < sizeNet; j++)
00453                         {
00454                                 if (IPAddress::maskedAddrAreEqual(network[j], entryRT->getHost(), getMask(network[j])))
00455                                 {
00456                                         EV << hostname << ": Posilam IP: " << entry.ipAddress << endl;
00457                                         entry.addressID = 2;
00458                                         entry.mustBeZero2 = 0;
00459                                         entry.mustBeZero3 = 0;
00460                                         entry.mustBeZero4 = 0;
00461                                         entry.ipAddress = entryRT->getHost();
00462                                         entry.metric = entryRT->getMetric();
00463                                         newEntry.push_back(entry);
00464                                 }
00465                         }
00466                 } // ...konec lokalnich adres
00467         } // for
00468 
00469 
00470         // ziskej redistribuvane site
00471         vector<RouteEntry> redistrEntry;
00472         bool red;
00473         if (redistr.redistrinute)
00474         {
00475                 EV << hostname << ": Redistribuce zapnuta" << endl;
00476                 // ziskani cest z OSPF
00477                 redistrEntry = getOSPFRoutes();
00478 
00479                 // OSPF dava do routovaci tabulky i primo pripojene site
00480                 // ty je nutne vyeliminovat
00481                 for(int j = 0; j < (int) redistrEntry.size(); j++)
00482                 {
00483                         red = true;
00484                         for (int i = 0; i < (int) ripIft.size(); i++)
00485                         {
00486                                 if (IPAddress::maskedAddrAreEqual(ripIft[i].addr.get4(), redistrEntry[j].ipAddress, ripIft[i].mask.get4()))
00487                                         red = false;
00488                         }
00489                         if (red)
00490                                 newEntry.push_back(redistrEntry[j]);
00491                 }
00492         }// ...if redistribuce
00493 
00494         return newEntry;
00495 }
00496 
00497 
00507 void RIPRouting::processRequest(RIPPacket *msg)
00508 {
00509         EV << "RIPRouting::processRequest" << endl;
00510    RouteEntry entryReq = msg->getRouteEntry(0);    // 1. zaznam z prichozi zpravy
00511 
00512    if ((msg->getRouteEntryArraySize() == 1) && (entryReq.addressID == 0) && (entryReq.metric == 16))
00513    {
00514       // ...posli aktualizacni zaznam se vsemi cestami
00515         this->sendPacket(Response, udpCtrl->getSrcAddr().get4());
00516    }
00517    else
00518    {
00519       // ... jinak posli jen pozadovane zaznamy
00520         // mozno udelat pri nejakem rozsireni, ale pri simulaci
00521         // prakticky nepouzitelne; pouziva se k siagnostickym ucelum
00522    }
00523 }
00524 
00533 void RIPRouting::processResponse(RIPPacket *msg)
00534 {
00535    // zkontroluj src port 520 (RIP), jinak ignoruj
00536    if ((udpCtrl->getSrcPort()) != destPort)
00537       return;
00538 
00539    int max = msg->getRouteEntryArraySize();     // pocet prijatych cest
00540    IPRoute *entryRT = new IPRoute();            // zaznam z routovaci tabulky
00541    int newMetric;                               // metrika ze zpravy
00542    int oldMetric;                               // metrika z routovaci tabulky
00543    bool change = false;                                                 // hlida zmeny, true = trigged zprava
00544 
00545    // prochazej vsechny prijate zaznamy
00546    for (int i = 0; i < max; i++)
00547    {
00548         // pokud nejde o IP adresu, preskoc zaznam
00549       if  (msg->getRouteEntry(i).addressID != 2)
00550          continue;
00551 
00552       // pokud je metrika vetsi nez infinite, preskoc zaznam
00553       if (msg->getRouteEntry(i).metric >= 16)
00554         continue;
00555 
00556       // loopbacky taky ignoruj
00557       if (IPAddress::maskedAddrAreEqual(msg->getRouteEntry(i).ipAddress, "127.0.0.0", "255.0.0.0"))
00558         continue;
00559 
00560       // adresy tridy D a E ignoruj taktez
00561       if (!(msg->getRouteEntry(i).ipAddress < "223.255.255.255"))
00562         continue;
00563 
00564       // najdi IP adresu v routovaci tabulce
00565       EV << hostname << ": Adresa " << i << ": "<< msg->getRouteEntry(i).ipAddress << endl;
00566       entryRT = const_cast<IPRoute*>(rt->findBestMatchingRoute(msg->getRouteEntry(i).ipAddress));
00567 
00568       // pro exitující twin
00569       if (checkTwin(entryRT))
00570       {
00571         EV << hostname << "Existuje dvojice, hledam routu" << endl;
00572         for (int k = 0; k < (int) routeTwins.size(); k++)
00573                         {
00574                                 if (entryRT == routeTwins[k].route1 || entryRT == routeTwins[k].route2)
00575                                 {
00576                                         EV << hostname << "Routa nalezena: " << endl;
00577                                         if (udpCtrl->getSrcAddr().get4() == routeTwins[k].route1->getGateway())
00578                                         {
00579                                                 entryRT = routeTwins[k].route1;
00580                                                 EV << entryRT->info() << endl;
00581                                         }
00582                                         else if (udpCtrl->getSrcAddr().get4() == routeTwins[k].route2->getGateway())
00583                                         {
00584                                                 entryRT = routeTwins[k].route2;
00585                                                 EV << entryRT->info() << endl;
00586                                         }
00587                                         break;
00588                                 }
00589                         }
00590       } //if twin
00591 
00592       // pokud adresa neni v routovaci tabulce, je treba pridat novy zaznam
00593       if (entryRT == NULL || ((entryRT->getGateway() != udpCtrl->getSrcAddr().get4()) && (msg->getRouteEntry(i).metric + 1 == entryRT->getMetric()) && !checkTwin(entryRT)))
00594       {
00595         IPRoute *entry = new IPRoute(); // nova cesta
00596         RIPRouteTwins twin;                                     // dvojice stejnych cest
00597                         int id;
00598 
00599                         // zjisti z jakeho interfacu zprava prisla
00600                         // kvuli urceni masky a adresy cesty
00601         for (int j = 0; j < (int) ripIft.size(); j++)
00602                                 if (ripIft[j].intID == udpCtrl->getInterfaceId())
00603                                 {
00604                                         id = j;
00605                                         break;
00606                                 }
00607 
00608         // pokud je adresa ze stejne tridy dostane masku podle masky na interfacu
00609         if (IPAddress::maskedAddrAreEqual(msg->getRouteEntry(i).ipAddress, ripIft[id].addr.get4(), getMask(msg->getRouteEntry(i).ipAddress)))
00610                 entry->setNetmask(ripIft[id].mask.get4());
00611         else
00612                 entry->setNetmask(getMask(msg->getRouteEntry(i).ipAddress));
00613 
00614         // vyplni vsechny potrebne informace a vlozi cestu do tabulky
00615         entry->setHost(msg->getRouteEntry(i).ipAddress);
00616         entry->setGateway(udpCtrl->getSrcAddr().get4());
00617         entry->setInterface(ift->getInterfaceById(udpCtrl->getInterfaceId()));
00618         entry->setType(INET_API IPRoute::REMOTE);
00619         entry->setSource(INET_API IPRoute::RIP);
00620         entry->setMetric(msg->getRouteEntry(i).metric + 1);
00621         rt->addRoute(entry);
00622         EV << "Pridavam adresu: "<< msg->getRouteEntry(i).ipAddress << endl;
00623 
00624         // jde o druhy zaznam stejne cesty
00625         if (entryRT != NULL)
00626         {
00627                 EV << hostname << ": Pridavam dvojcata: " << endl;
00628                 twin.route1 = entryRT;
00629                 twin.route2 = entry;
00630                 EV << twin.route1->info() << endl;
00631                 EV << twin.route2->info() << endl;
00632                 routeTwins.push_back(twin);
00633         }
00634                         // zaznam do RouteEntry + nastavi timer timeout
00635         RIPRouteTimer newEntry;
00636         newEntry.route = entry;
00637         newEntry.timer = updateTimer(timeout, NULL);
00638         routeTimer.push_back(newEntry);
00639       }
00640       // adresa jiz v routovaci tabulce je a nejedna se o druhou cestu do stejného místa
00641       else
00642       {
00643         EV << hostname << ": K teto adrese sedi adresa: " << entryRT->getHost() << endl;
00644                         newMetric = msg->getRouteEntry(i).metric;
00645                         oldMetric = entryRT->getMetric();
00646                         int j = getTimerRT(entryRT);
00647 
00648                         // updatuj timery
00649                         if (entryRT->getGateway() == udpCtrl->getSrcAddr().get4())
00650                                 updateTimer(timeout, &routeTimer[j]);
00651 
00652                         // pokud je nova metrika mensi nez metrika v tabulce,
00653                         // prepis ji a zapis novou adresu gateway (next hop)
00654                         if (((newMetric + 1) < oldMetric))
00655                         {
00656                                 EV << "Stara metrika: " << oldMetric << ". Nova metrika: " << newMetric << endl;
00657                                 entryRT->setMetric(newMetric + 1);
00658                                 entryRT->setGateway(udpCtrl->getSrcAddr().get4());
00659 
00660                                 // nastavi upravene ceste spravny odkaz na interface
00661                                 for (int k = 0; k < (int) ripIft.size(); k++)
00662                                 {
00663                                         if (udpCtrl->getInterfaceId() == ripIft[k].intID)
00664                                         {
00665                                                 entryRT->setInterface(ripIft[k].entry);
00666                                                 break;
00667                                         }
00668                                 }
00669                                 // vysle updaty
00670                                 change = true;
00671                         }
00672       } // else
00673    } // for
00674 
00675    // vysle updat
00676    if (change == true)
00677         sendTrigger();
00678 }
00679 
00691 void RIPRouting::processPacket(cMessage *msg)
00692 {
00693    int max;                                                                                                     // pocet cest v prichozi zprave
00694    cPacket *packet = dynamic_cast<cPacket *> (msg);                     // pretipujeme na cPacket
00695    udpCtrl = new UDPControlInfo();                                                      // naalokujeme misto pro UDP kontrolni info
00696    udpCtrl = dynamic_cast<UDPControlInfo *>(packet->getControlInfo());
00697    IPvXAddress srcIP = udpCtrl->getSrcAddr();                           // IP adresa zdroje
00698    RIPPacket *hMsg = dynamic_cast<RIPPacket *> (msg);           // pretipujeme na RIP zpravu
00699    IPRoute * route = new IPRoute();                                                     // naalokujeme cestu z RT
00700    EV << hostname << ": IP adresa zdroje RIP zpravy je:" << srcIP << endl;
00701 
00702    // zkontroluj IP adresu zdroje
00703    // sit zdroje neni v routovaci tabulce nebo neni primo pripojena
00704    if ((route = const_cast<IPRoute*> (rt->findBestMatchingRoute(srcIP.get4()))) == NULL)
00705    {
00706       error("Nejspise se jedna o podvrzenou zpravu, chybna zdrojova IP adresa1");
00707       return;
00708    }
00709    else if (route->getType() !=  INET_API IPRoute::DIRECT)
00710    {
00711       error("Nejspise se jedna o podvrzenou zpravu, chybna zdrojova IP adresa2");
00712       return;
00713    }
00714 
00715    // zkontroluj verzi a prislusna policka na spravnost
00716    switch(hMsg->getVersion())
00717    {
00718       case 0:
00719          return;
00720       case 1:
00721          if (!(hMsg->getMustBeZero1() == 0))
00722             return;
00723          max = hMsg->getRouteEntryArraySize();
00724 
00725          for (int i = 0; i < max; i++)
00726          {
00727             if  (!(hMsg->getRouteEntry(i).mustBeZero2 == 0))
00728                return;
00729             if  (!(hMsg->getRouteEntry(i).mustBeZero3 == 0))
00730                return;
00731             if  (!(hMsg->getRouteEntry(i).mustBeZero4 == 0))
00732                return;
00733           }
00734          break;
00735       default:
00736          break;
00737    }
00738 
00739    // dale zpracovavej podle toho, zda se jedna o Request nebo Response
00740    if (hMsg->getCommand() == Request)
00741       this->processRequest(hMsg);
00742    else if (hMsg->getCommand() == Response)
00743       this->processResponse(hMsg);
00744    delete msg;
00745 }
00746 
00756 void RIPRouting::initialize (int stage)
00757 {
00758    // v stage 2 se registruji interfacy
00759    if (stage == 3)
00760    {
00761            // nastaveni portu a spojeni s portem
00762            localPort = par("localPort");
00763            destPort = par("destPort");
00764            bindToPort(localPort);
00765 
00766            // routovaci tabulka, tabulka interfacu
00767            // notifikacni tabulka a odebirani upozorneni
00768            rt = RoutingTableAccess().get();
00769            ift = InterfaceTableAccess().get();
00770            nb = NotificationBoardAccess().get();
00771            nb->subscribe(this, NF_INTERFACE_STATE_CHANGED);
00772 
00773            // dalsi inicializace
00774            triggerTimer = NULL;
00775            redistr.redistrinute = false;
00776            redistr.metric = 0;
00777 
00778       // vlastni tabulka interfacu s info, ktere potrebuji
00779       InterfaceEntry *entryIFT = new InterfaceEntry();
00780       for (int i = 0; i < ift->getNumInterfaces(); i++)
00781       {
00782         entryIFT = ift->getInterface(i);
00783         insertIft(entryIFT);
00784       }
00785 
00786       // zpracovani XML konfigurace pro RIP
00787       hostname = par("hostname");
00788                 const char *fileName = par("configFile");
00789                 if (!LoadConfigFromXML(fileName))
00790                         return;
00791 
00792                 // sledování klíčových proměnných
00793                 WATCH_VECTOR(ripIft);
00794                 WATCH_VECTOR(network);
00795                 WATCH_VECTOR(routeTimer);
00796                 WATCH(redistr);
00797 
00798       // zapni hello timer
00799       RIPTimer *msg = new RIPTimer("Hello");
00800       msg->setTimerKind(hello);
00801       scheduleAt(simTime() + 30.0 + exponential(1), msg);
00802 
00803       // vysli requesty vsem sousedum
00804       this->sendPacket(Request, BROADCAST);
00805    }
00806 }
00807 
00817 void RIPRouting::handleMessage(cMessage *msg)
00818 {
00819         EV << hostname << "RIPRouting::handleMessage" << endl;
00820    vector<RouteEntry> newEntry;
00821    IPAddress mask;
00822    int size;
00823    int i;
00824 
00825    // vlastni zprava, tj. nektery z casovacu
00826    if (msg->isSelfMessage())
00827    {
00828         RIPTimer *timer = check_and_cast <RIPTimer *> (msg);
00829         switch(timer->getTimerKind())
00830       {
00831                         case hello:
00832             // hello packet (30s)
00833                 EV << hostname << ": Prisel hello." << endl;
00834             this->sendPacket(Response, BROADCAST);
00835             updateTimer(hello, NULL);
00836             delete timer;
00837             break;
00838 
00839                         case timeout:
00840             // vyprsel garbage-collection timer (120s)
00841                 EV << hostname << ": Prisel timeout." << endl;
00842                 i = getRouteRT(timer);
00843                 routeTimer[i].route->setMetric(16);
00844                 updateTimer(garbage, &routeTimer[i]);
00845                 sendTrigger();
00846                 delete timer;
00847             break;
00848 
00849                         case garbage:
00850             // vymaz cestu, timout (180s)
00851                 EV << hostname << ": Prisel garbage." << endl;
00852                 i = getRouteRT(timer);
00853                 EV << hostname << ": Vyprsel garbage na adrese: " << routeTimer[i].route->getHost() << endl;
00854                 EV << hostname << ": Mazu cestu: " << routeTimer[i].route->info() << endl;
00855                                 rt->deleteRoute(routeTimer[i].route);
00856                                 routeTimer.erase(routeTimer.begin() + i);
00857                 delete timer;
00858             break;
00859 
00860          case trigger:
00861                                 // hello packet (30s)
00862                                 EV << "Prisel trigger." << endl;
00863                                 size = rt->getNumRoutes();
00864                                 this->sendPacket(Response, BROADCAST);
00865                                 delete triggerTimer;
00866                                 triggerTimer = NULL;
00867                                 break;
00868 
00869          default:
00870                 delete timer;
00871       }
00872    }
00873    // cizi RIP zprava
00874    else if (dynamic_cast<RIPPacket *>(msg))
00875         this->processPacket(msg);
00876    else
00877         EV << "ICMP ERROR nebo jina zprava" << endl;
00878 }
00879 
00890 bool RIPRouting::LoadConfigFromXML(const char *filename)
00891 {
00892         // nacteni dokumentu
00893    cXMLElement* asConfig = ev.getXMLDocument(filename);
00894    if (asConfig == NULL)
00895        return false;
00896 
00897    // prvni element <Router id="192.168.10.7">
00898    std::string routerXPath("Router[@id='");
00899    IPAddress routerId = rt->getRouterId();
00900    routerXPath += routerId.str();
00901         routerXPath += "']";
00902 
00903         cXMLElement* routerNode = asConfig->getElementByPath(routerXPath.c_str());
00904         if (routerNode == NULL)
00905         {
00906                 error("No configuration for Router ID: %s", routerId.str().c_str());
00907            return false;
00908         }
00909 
00910         cXMLElement* routingNode = routerNode->getElementByPath("Routing");
00911         if (routingNode == NULL)
00912                  return false;
00913 
00914    cXMLElement* ripNode = routingNode->getElementByPath("Rip");
00915    if (ripNode == NULL)
00916        return false;
00917 
00918    // vypis siti, ktere se maji propagovat v RIP zpravach
00919    cXMLElementList childrenNodes = ripNode->getChildrenByTagName("Network");
00920    if (childrenNodes.size() > 0)
00921    {
00922       for (cXMLElementList::iterator node = childrenNodes.begin(); node != childrenNodes.end(); node++)
00923       {
00924          network.push_back(ULongFromAddressString((*node)->getNodeValue()));
00925       }
00926    }
00927    else
00928       return false;
00929 
00930    // vypis pasivnich interfacu, na ktere se nemaji zasilat RIP zpravy
00931    childrenNodes = ripNode->getChildrenByTagName("Passive-interface");
00932         if (childrenNodes.size() > 0)
00933         {
00934                 for (cXMLElementList::iterator node = childrenNodes.begin(); node != childrenNodes.end(); node++)
00935                 {
00936                         int id = ift->getInterfaceByName((*node)->getNodeValue())->getInterfaceId();
00937                         for (int i = 0; i < (int) ripIft.size(); i++)
00938                         {
00939                                 if (ripIft[i].intID == id)
00940                                 {
00941                                         ripIft[i].passive = true;
00942                                         break;
00943                                 }
00944                         }
00945                 }
00946         }
00947 
00948         // nacteni elementu redistribuce
00949         cXMLElement* redistrNode = ripNode->getElementByPath("Redistribute");
00950         if (redistrNode == NULL)
00951                 return true;
00952 
00953         // nacteni protokolu, ze ktereho se bude redistribuvota (ospf)
00954         cXMLElement* protocolNode = redistrNode->getElementByPath("Protocol");
00955         if (protocolNode == NULL)
00956         {
00957                  error("Pro redistribuci neni definovan protokol.");
00958                  return false;
00959         }
00960         else
00961                 redistr.protocol = (char *) protocolNode->getNodeValue();
00962 
00963         // nacteni metriky, ktera se priradi cizim cestam
00964         cXMLElement* metricNode = redistrNode->getElementByPath("Metric");
00965         if (metricNode == NULL)
00966         {
00967                  error("Pro redistribuci neni definovana metrika.");
00968                  return false;
00969         }
00970         else
00971                 redistr.metric = atol(metricNode->getNodeValue());
00972 
00973    redistr.redistrinute = true;
00974    return true;
00975 }
00976 
00988 void RIPRouting::receiveChangeNotification(int category, const cPolymorphic *details)
00989 {
00990         // ignoruj notifikaci behem inicializace
00991    if (simulation.getContextType() == CTX_INITIALIZE)
00992        return;
00993 
00994    Enter_Method_Silent();
00995    printNotificationBanner(category, details);
00996 
00997 
00998    // notifikace na rozhrani
00999    if (category == NF_INTERFACE_STATE_CHANGED)
01000    {
01001        InterfaceEntry *entry = check_and_cast<InterfaceEntry*>(details);
01002        int i = 0;
01003 
01004                  // Interface je DOWN
01005        if (entry->isDown())
01006        {
01007          EV << hostname << ": Interface je DOWN\n";
01008 
01009          // vymaz primou cestu z tabulky a uloz ji do struktury intDown
01010          for (i = 0; i < (int) rt->getNumRoutes(); i++)
01011          {
01012                  if (rt->getRoute(i)->getType() == INET_API IPRoute::DIRECT)
01013                  {
01014                          if (rt->getRoute(i)->getInterface() == entry)
01015                          {
01016                                  EV << "Mazu cestu: " << rt->getRoute(i)->info() << endl;
01017                                  IPRoute *entryRT = new IPRoute();
01018                                  //entryRT = const_cast<IPRoute*> (rt->getRoute(i));
01019                                  entryRT->setHost(rt->getRoute(i)->getHost());
01020                                  entryRT->setGateway(rt->getRoute(i)->getGateway());
01021                                  entryRT->setNetmask(rt->getRoute(i)->getNetmask());
01022                                                  entryRT->setInterface(entry);
01023                                                  entryRT->setType(INET_API IPRoute::DIRECT);
01024                                                  entryRT->setSource(INET_API IPRoute::IFACENETMASK);
01025                                                  entryRT->setMetric(1);
01026                                  rt->deleteRoute(rt->getRoute(i));
01027                                  intDown.push_back(entryRT);
01028                          }
01029                  }
01030          }
01031 
01032          // vymaz cestu i z interni tabulky rozhraní ripIft
01033          for (i = 0; i < (int) ripIft.size(); i++)
01034          {
01035                  if (ripIft[i].entry == entry)
01036                          ripIft.erase(ripIft.begin() + i);
01037          }
01038 
01039          // vzdalene cesty smaz taky
01040          for(i = 0; i < (int) routeTimer.size(); i++)
01041          {
01042                                  if (routeTimer[i].route->getInterface() == entry)
01043                                  {
01044                                          EV << "Mazu cestu: " << routeTimer[i].route->info() << endl;
01045 
01046                                          // zrusit a samzat jeji casovac
01047                                          if (routeTimer[i].timer->isScheduled())
01048                                                  cancelEvent(routeTimer[i].timer);
01049                                          delete routeTimer[i].timer;
01050 
01051                                          // v pripade, ze cesta má dvojici, vymaz zaznam z checkTwin
01052                                          if (checkTwin(routeTimer[i].route))
01053                                          {
01054                                                  for (int j = 0; j < (int) routeTwins.size(); j++)
01055                                                  {
01056                                                          if (routeTimer[i].route == routeTwins[j].route1 || routeTimer[i].route == routeTwins[j].route2)
01057                                                                  routeTwins.erase(routeTwins.begin() + j);
01058                                                  }
01059                                          }
01060                                          // vymazat cestu a jeji znaznam v routeTimer
01061                                          rt->deleteRoute(routeTimer[i].route);
01062                                          routeTimer.erase(routeTimer.begin() + i);
01063                                          i--;
01064                                  }
01065                          }
01066        }
01067        // Interface je UP
01068        else
01069        {
01070          EV << hostname << ": Interface je UP\n";
01071 
01072          // vlozime zpet do RT prime cesty
01073          for(i = 0; i < (int) intDown.size(); i++)
01074          {
01075                  if (intDown[i]->getInterface() ==  entry)
01076                  {
01077                          rt->addRoute(intDown[i]);
01078                          intDown.erase(intDown.begin() + i);
01079                  }
01080          }
01081          // vloz zaznam do ripIft
01082          insertIft(entry);
01083        }
01084        // rozesli aktualizace
01085        sendTrigger();
01086     }
01087 }
01088 
01098 vector<RouteEntry> RIPRouting::getOSPFRoutes()
01099 {
01100         // redistribujeme z protokolu OSPF?
01101         vector<RouteEntry> newEntry;                            // vektor zasilanych adres
01102         if (strcmp(redistr.protocol, "ospf"))
01103                 return newEntry;
01104 
01105         // proměnné
01106         IPRoute *entryRT = new IPRoute();           // routovaci tabulka
01107         int sizeTab = rt->getNumRoutes();                       // velikost routovací tabulky
01108         RouteEntry entry;                               // nova polozka s adresou
01109 
01110         // ber postupne site z routovaci tabulky a kontroluj je
01111         for (int i = 0; i < sizeTab; i++)
01112         {
01113                 entryRT = const_cast<IPRoute*>(rt->getRoute(i));
01114                 if (entryRT->getSource() == INET_API IPRoute::OSPF)
01115                 {
01116                         // pridava RIP cestu
01117                         entry.addressID = 2;
01118                         entry.mustBeZero2 = 0;
01119                         entry.mustBeZero3 = 0;
01120                         entry.mustBeZero4 = 0;
01121                         entry.ipAddress = entryRT->getHost();
01122                         EV << "Posilam podle RIP zaznamu IP: " << entry.ipAddress << endl;
01123                         entry.metric = redistr.metric;
01124                         newEntry.push_back(entry);
01125                         continue;
01126                 }
01127         }
01128 
01129         return newEntry;
01130 }