INET Framework for OMNeT++/OMNEST
AnsaRoutingTable.cc
Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004-2006 Andras Varga
00003 // Copyright (C) 2000 Institut fuer Telematik, Universitaet Karlsruhe
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 //
00019 
00020 
00021 //  Cleanup and rewrite: Andras Varga, 2004
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <algorithm>
00028 #include <sstream>
00029 
00030 #include "AnsaRoutingTable.h"
00031 #include "RoutingTableXmlParser.h"
00032 #include "IPRoute.h"
00033 #include "IPv4InterfaceData.h"
00034 #include "IInterfaceTable.h"
00035 #include "InterfaceTableAccess.h"
00036 #include "NotifierConsts.h"
00037 
00038 
00039 Define_Module(AnsaRoutingTable);
00040 
00041 std::ostream& operator<<(std::ostream& os, const IPRoute& e);
00042 
00043 AnsaRoutingTable::AnsaRoutingTable()
00044 {
00045  // DSDV 
00046     timetolive_routing_entry = timetolive_routing_entry.getMaxTime();
00047     initializeAD();
00048 }
00049 
00050 AnsaRoutingTable::~AnsaRoutingTable()
00051 {
00052     for (unsigned int i=0; i<routes.size(); i++)
00053         delete routes[i];
00054     for (unsigned int i=0; i<multicastRoutes.size(); i++)
00055         delete multicastRoutes[i];
00056 }
00057 
00058 //
00059 
00060 void AnsaRoutingTable::initializeAD()
00061 {
00062   ADmap[IPRoute::MANUAL]=1;
00063   ADmap[IPRoute::IFACENETMASK]=0;
00064   ADmap[IPRoute::RIP]=120;
00065   ADmap[IPRoute::OSPF]=110;
00066   ADmap[IPRoute::BGP]=20;
00067 }
00068 void AnsaRoutingTable::initialize(int stage)
00069 {
00070     if (stage==0)
00071     {
00072         // get a pointer to the NotificationBoard module and IInterfaceTable
00073         nb = NotificationBoardAccess().get();
00074         ift = InterfaceTableAccess().get();
00075 
00076         IPForward = par("IPForward").boolValue();
00077 
00078         nb->subscribe(this, NF_INTERFACE_CREATED);
00079         nb->subscribe(this, NF_INTERFACE_DELETED);
00080         nb->subscribe(this, NF_INTERFACE_STATE_CHANGED);
00081         nb->subscribe(this, NF_INTERFACE_CONFIG_CHANGED);
00082         nb->subscribe(this, NF_INTERFACE_IPv4CONFIG_CHANGED);
00083 
00084         WATCH_VECTOR(showIPRoute);   //
00085         WATCH_PTRVECTOR(multicastRoutes);
00086         WATCH(IPForward);
00087         WATCH(routerId);
00088     }
00089     else if (stage==1)
00090     {
00091         // L2 modules register themselves in stage 0, so we can only configure
00092         // the interfaces in stage 1.
00093         const char *filename = par("configFile");
00094 
00095         // At this point, all L2 modules have registered themselves (added their
00096         // interface entries). Create the per-interface IPv4 data structures.
00097         IInterfaceTable *interfaceTable = InterfaceTableAccess().get();
00098         for (int i=0; i<interfaceTable->getNumInterfaces(); ++i)
00099             configureInterfaceForIPv4(interfaceTable->getInterface(i));
00100         
00101         
00102         const char *routerIdStr = par("routerId").stringValue();
00103         
00104         // read routing table file (and interface configuration)
00105         RoutingTableXmlParser parser(ift, this);
00106         if (*filename && !parser.readRoutingTableFromXml(filename, routerIdStr))
00107             error("Error reading routing table file %s", filename);
00108 
00109         // set routerId if param is not "" (==no routerId) or "auto" (in which case we'll
00110         // do it later in stage 3, after network configurators configured the interfaces)
00111         
00112         if (strcmp(routerIdStr, "") && strcmp(routerIdStr, "auto"))
00113             routerId = IPAddress(routerIdStr);
00114     }
00115     else if (stage==3)
00116     {
00117         // routerID selection must be after stage==2 when network autoconfiguration
00118         // assigns interface addresses
00119         configureRouterId();
00120 
00121         // we don't use notifications during initialize(), so we do it manually.
00122         // Should be in stage=3 because autoconfigurator runs in stage=2.
00123         updateNetmaskRoutes();
00124 
00125         //printRoutingTable();
00126     }
00127 }
00128 
00129 void AnsaRoutingTable::configureRouterId()
00130 {
00131     if (routerId.isUnspecified())  // not yet configured
00132     {
00133         const char *routerIdStr = par("routerId").stringValue();
00134         if (!strcmp(routerIdStr, "auto"))  // non-"auto" cases already handled in stage 1
00135         {
00136             // choose highest interface address as routerId
00137             for (int i=0; i<ift->getNumInterfaces(); ++i)
00138             {
00139                 InterfaceEntry *ie = ift->getInterface(i);
00140                 if (!ie->isLoopback() && ie->ipv4Data()->getIPAddress().getInt() > routerId.getInt())
00141                     routerId = ie->ipv4Data()->getIPAddress();
00142             }
00143         }
00144     }
00145     else // already configured
00146     {
00147         // if there is no interface with routerId yet, assign it to the loopback address;
00148         // TODO find out if this is a good practice, in which situations it is useful etc.
00149         if (getInterfaceByAddress(routerId)==NULL)
00150         {
00151             InterfaceEntry *lo0 = ift->getFirstLoopbackInterface();
00152             lo0->ipv4Data()->setIPAddress(routerId);
00153             lo0->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00154         }
00155     }
00156 }
00157 
00158 void AnsaRoutingTable::updateDisplayString()
00159 {
00160     if (!ev.isGUI())
00161         return;
00162 
00163     char buf[80];
00164     if (routerId.isUnspecified())
00165         sprintf(buf, "%d+%d routes", routes.size(), multicastRoutes.size());
00166     else
00167         sprintf(buf, "routerId: %s\n%d+%d routes", routerId.str().c_str(), routes.size(), multicastRoutes.size());
00168     getDisplayString().setTagArg("t",0,buf);
00169 }
00170 
00171 void AnsaRoutingTable::handleMessage(cMessage *msg)
00172 {
00173     opp_error("This module doesn't process messages");
00174 }
00175 
00176 void AnsaRoutingTable::receiveChangeNotification(int category, const cPolymorphic *details)
00177 {
00178     if (simulation.getContextType()==CTX_INITIALIZE)
00179         return;  // ignore notifications during initialize
00180 
00181     Enter_Method_Silent();
00182     printNotificationBanner(category, details);
00183 
00184     if (category==NF_INTERFACE_CREATED)
00185     {
00186         // add netmask route for the new interface
00187         updateNetmaskRoutes();
00188     }
00189     else if (category==NF_INTERFACE_DELETED)
00190     {
00191         // remove all routes that point to that interface
00192         InterfaceEntry *entry = check_and_cast<InterfaceEntry*>(details);
00193         deleteInterfaceRoutes(entry);
00194     }
00195     else if (category==NF_INTERFACE_STATE_CHANGED)
00196     {
00197         updateNetmaskRoutes();
00198     }
00199     else if (category==NF_INTERFACE_CONFIG_CHANGED)
00200     {
00201         invalidateCache();
00202     }
00203     else if (category==NF_INTERFACE_IPv4CONFIG_CHANGED)
00204     {
00205         // if anything IPv4-related changes in the interfaces, interface netmask
00206         // based routes have to be re-built.
00207         updateNetmaskRoutes();
00208     }
00209 }
00210 
00211 void AnsaRoutingTable::deleteInterfaceRoutes(InterfaceEntry *entry)
00212 {
00213     RouteVector::iterator it = routes.begin();
00214     while (it != routes.end())
00215     {
00216         IPRoute *route = *it;
00217         if (route->getInterface() == entry)
00218         {
00219             deleteRoute(route);
00220             it = routes.begin();  // iterator became invalid -- start over
00221         }
00222         else
00223         {
00224             ++it;
00225         }
00226     }
00227 }
00228 
00229 void AnsaRoutingTable::invalidateCache()
00230 {
00231     routingCache.clear();
00232     localAddresses.clear();
00233 }
00234 
00235 void AnsaRoutingTable::printRoutingTable() const
00236 {
00237     EV << "-- Routing table --\n";
00238     ev.printf("%-16s %-16s %-16s %-3s %s\n",
00239               "Destination", "Gateway", "Netmask", "Iface");
00240 
00241     for (int i=0; i<getNumRoutes(); i++)
00242         EV << getRoute(i)->detailedInfo() << "\n";
00243     EV << "\n";
00244 }
00245 
00246 std::vector<IPAddress> AnsaRoutingTable::gatherAddresses() const
00247 {
00248     std::vector<IPAddress> addressvector;
00249 
00250     for (int i=0; i<ift->getNumInterfaces(); ++i)
00251         addressvector.push_back(ift->getInterface(i)->ipv4Data()->getIPAddress());
00252     return addressvector;
00253 }
00254 
00255 //---
00256 
00257 void AnsaRoutingTable::configureInterfaceForIPv4(InterfaceEntry *ie)
00258 {
00259     IPv4InterfaceData *d = new IPv4InterfaceData();
00260     ie->setIPv4Data(d);
00261 
00262     // metric: some hints: OSPF cost (2e9/bps value), MS KB article Q299540, ...
00263     d->setMetric((int)ceil(2e9/ie->getDatarate())); // use OSPF cost as default
00264 }
00265 
00266 InterfaceEntry *AnsaRoutingTable::getInterfaceByAddress(const IPAddress& addr) const
00267 {
00268     Enter_Method("getInterfaceByAddress(%x)", addr.getInt()); // note: str().c_str() too slow here
00269 
00270     if (addr.isUnspecified())
00271         return NULL;
00272     for (int i=0; i<ift->getNumInterfaces(); ++i)
00273     {
00274         InterfaceEntry *ie = ift->getInterface(i);
00275         if (ie->ipv4Data()->getIPAddress()==addr)
00276             return ie;
00277     }
00278     return NULL;
00279 }
00280 
00281 
00282 void AnsaRoutingTable::configureLoopbackForIPv4()
00283 {
00284     InterfaceEntry *ie = ift->getFirstLoopbackInterface();
00285 
00286     // add IPv4 info. Set 127.0.0.1/8 as address by default --
00287     // we may reconfigure later it to be the routerId
00288     IPv4InterfaceData *d = new IPv4InterfaceData();
00289     d->setIPAddress(IPAddress::LOOPBACK_ADDRESS);
00290     d->setNetmask(IPAddress::LOOPBACK_NETMASK);
00291     d->setMetric(1);
00292     ie->setIPv4Data(d);
00293 }
00294 
00295 //---
00296 
00297 bool AnsaRoutingTable::isLocalAddress(const IPAddress& dest) const
00298 {
00299     Enter_Method("isLocalAddress(%x)", dest.getInt()); // note: str().c_str() too slow here
00300 
00301     if (localAddresses.empty())
00302     {
00303         // collect interface addresses if not yet done
00304         for (int i=0; i<ift->getNumInterfaces(); i++)
00305         {
00306             IPAddress interfaceAddr = ift->getInterface(i)->ipv4Data()->getIPAddress();
00307             localAddresses.insert(interfaceAddr);
00308         }
00309     }
00310 
00311     AddressSet::iterator it = localAddresses.find(dest);
00312     return it!=localAddresses.end();
00313 }
00314 
00315 bool AnsaRoutingTable::isLocalMulticastAddress(const IPAddress& dest) const
00316 {
00317     Enter_Method("isLocalMulticastAddress(%x)", dest.getInt()); // note: str().c_str() too slow here
00318 
00319     for (int i=0; i<ift->getNumInterfaces(); i++)
00320     {
00321         InterfaceEntry *ie = ift->getInterface(i);
00322         for (unsigned int j=0; j < ie->ipv4Data()->getMulticastGroups().size(); j++)
00323             if (dest.equals(ie->ipv4Data()->getMulticastGroups()[j]))
00324                 return true;
00325     }
00326     return false;
00327 }
00328 
00329 void AnsaRoutingTable::dsdvTestAndDelete()
00330 {
00331      if (timetolive_routing_entry==timetolive_routing_entry.getMaxTime())
00332            return;
00333      for (RouteVector::iterator i=routes.begin(); i!=routes.end(); ++i)
00334      {
00335 
00336            IPRoute *e = *i;
00337            if (this->isLocalAddress(e->getHost()))
00338                      continue;
00339            if (((e->getHost()).str() != "*") && ((e->getHost()).str() != "<unspec>") && ((e->getHost()).str() != "127.0.0.1") && (simTime()-(getInstallTime()))>timetolive_routing_entry){
00340                 //EV << "Routes ends at" << routes.end() <<"\n";
00341                 deleteRoute(e);
00342                 //EV << "After deleting Routes ends at" << routes.end() <<"\n";
00343                 EV << "Deleting entry ip=" << e->getHost().str() <<"\n";
00344                 i--;
00345            }
00346       }
00347 
00348 }
00349 
00350 const bool AnsaRoutingTable::testValidity(const IPRoute *entry) const
00351 {
00352      if (timetolive_routing_entry==timetolive_routing_entry.getMaxTime())
00353            return true;
00354      if (this->isLocalAddress(entry->getHost()))
00355            return true;
00356      if (((entry->getHost()).str() != "*") && ((entry->getHost()).str() != "<unspec>") && ((entry->getHost()).str() != "127.0.0.1") && (simTime()-(getInstallTime()))>timetolive_routing_entry){
00357                 return false;
00358       }
00359       return true;
00360 
00361 }
00362 
00363 const IPRoute *AnsaRoutingTable::findBestMatchingRoute(const IPAddress& dest) const
00364 {
00365     Enter_Method("findBestMatchingRoute(%x)", dest.getInt()); // note: str().c_str() too slow here
00366     RoutingCache::iterator it = routingCache.find(dest);
00367 
00368     if (it != routingCache.end())
00369     {
00370         if (it->second==NULL)
00371         {
00372               routingCache.clear();
00373               localAddresses.clear();
00374         }
00375         else if (testValidity(it->second))
00376             {
00377                  return it->second;
00378         }
00379     }
00380 
00381     // find best match (one with longest prefix)
00382     // default route has zero prefix length, so (if exists) it'll be selected as last resort
00383     const IPRoute *bestRoute = NULL;
00384     uint32 longestNetmask = 0;
00385     for (RouteVector::const_iterator i=routes.begin(); i!=routes.end(); ++i)
00386     {
00387         IPRoute *e = *i;
00388         if (testValidity(e))
00389         {
00390            if (IPAddress::maskedAddrAreEqual(dest, e->getHost(), e->getNetmask()) &&  // match
00391                (!bestRoute || e->getNetmask().getInt() > longestNetmask))  // longest so far
00392            {
00393               bestRoute = e;
00394               longestNetmask = e->getNetmask().getInt();
00395            }
00396         }
00397     }
00398     
00399     if (bestRoute && bestRoute->getHost()!=dest)
00400     {
00401         bestRoute=NULL;
00402         /* in this case we must find the mask must be 255.255.255.255 route */
00403         for (RouteVector::const_iterator i=routes.begin(); i!=routes.end(); ++i)
00404         {
00405            IPRoute *e = *i;
00406            if (testValidity(e))
00407            {
00408               if (IPAddress::maskedAddrAreEqual(dest, e->getHost(), IPAddress::ALLONES_ADDRESS) &&  // match
00409                (!bestRoute || e->getNetmask().getInt()>longestNetmask))  // longest so far
00410               {
00411                  bestRoute = e;
00412                  longestNetmask = e->getNetmask().getInt();
00413               }
00414            }
00415         }
00416     }
00417 
00418     routingCache[dest] = bestRoute;
00419     return bestRoute;
00420 }
00421 
00422 InterfaceEntry *AnsaRoutingTable::getInterfaceForDestAddr(const IPAddress& dest) const
00423 {
00424     Enter_Method("getInterfaceForDestAddr(%x)", dest.getInt()); // note: str().c_str() too slow here
00425 
00426     const IPRoute *e = findBestMatchingRoute(dest);
00427     return e ? e->getInterface() : NULL;
00428 }
00429 
00430 IPAddress AnsaRoutingTable::getGatewayForDestAddr(const IPAddress& dest) const
00431 {
00432     Enter_Method("getGatewayForDestAddr(%x)", dest.getInt()); // note: str().c_str() too slow here
00433 
00434     const IPRoute *e = findBestMatchingRoute(dest);
00435     return e ? e->getGateway() : IPAddress();
00436 }
00437 
00438 
00439 MulticastRoutes AnsaRoutingTable::getMulticastRoutesFor(const IPAddress& dest) const
00440 {
00441     Enter_Method("getMulticastRoutesFor(%x)", dest.getInt()); // note: str().c_str() too slow here here
00442 
00443     MulticastRoutes res;
00444     res.reserve(16);
00445     for (RouteVector::const_iterator i=multicastRoutes.begin(); i!=multicastRoutes.end(); ++i)
00446     {
00447         const IPRoute *e = *i;
00448         if (IPAddress::maskedAddrAreEqual(dest, e->getHost(), e->getNetmask()))
00449         {
00450             MulticastRoute r;
00451             r.interf = e->getInterface();
00452             r.gateway = e->getGateway();
00453             res.push_back(r);
00454         }
00455     }
00456     return res;
00457 }
00458 
00459 
00460 int AnsaRoutingTable::getNumRoutes() const
00461 {
00462     return routes.size()+multicastRoutes.size();
00463 }
00464 
00465 const IPRoute *AnsaRoutingTable::getRoute(int k) const
00466 {
00467     if (k < (int)routes.size())
00468         return routes[k];
00469     k -= routes.size();
00470     if (k < (int)multicastRoutes.size())
00471         return multicastRoutes[k];
00472     return NULL;
00473 }
00474 
00475 const IPRoute *AnsaRoutingTable::getDefaultRoute() const
00476 {
00477     int n = (int)routes.size();
00478     for (int i=0; i<n; i++)
00479         if (routes[i]->getNetmask().isUnspecified())
00480             return routes[i];
00481     return NULL;
00482 }
00483 
00484 const IPRoute *AnsaRoutingTable::findRoute(const IPAddress& target, const IPAddress& netmask,
00485     const IPAddress& gw, int metric, const char *dev) const
00486 {
00487     int n = getNumRoutes();
00488     for (int i=0; i<n; i++)
00489         if (routeMatches(getRoute(i), target, netmask, gw, metric, dev))
00490             return getRoute(i);
00491     return NULL;
00492 }
00493 
00494 void AnsaRoutingTable::addRoute(const IPRoute *entry)
00495 {
00496     Enter_Method("addRoute(...)");
00497 
00498     // check for null address and default route
00499     if (entry->getHost().isUnspecified() != entry->getNetmask().isUnspecified())
00500         error("addRoute(): to add a default route, set both host and netmask to zero");
00501 
00502     if (entry->getHost().doAnd(entry->getNetmask().isUnspecified()).getInt() != 0)
00503         error("addRoute(): suspicious route: host %s has 1-bits outside netmask %s",
00504               entry->getHost().str().c_str(), entry->getNetmask().str().c_str());
00505 
00506     // check that the interface exists
00507     
00508     if (!entry->getInterface())
00509         error("addRoute(): interface cannot be NULL");
00510     if (checkRoute(entry))
00511     {
00512       // if this is a default route, remove old default route (we're replacing it)
00513       if (entry->getNetmask().isUnspecified() && getDefaultRoute()!=NULL)
00514           deleteRoute(getDefaultRoute());
00515 
00516       // add to tables
00517       if (!entry->getHost().isMulticast())
00518           routes.push_back(const_cast<IPRoute*>(entry));
00519       else
00520           multicastRoutes.push_back(const_cast<IPRoute*>(entry));
00521 
00522       invalidateCache();
00523       updateDisplayString();
00524 
00525       nb->fireChangeNotification(NF_IPv4_ROUTE_ADDED, entry);
00526     }
00527     generateShowIPRoute();
00528 }
00529 
00530 
00531 bool AnsaRoutingTable::deleteRoute(const IPRoute *entry)
00532 {
00533     Enter_Method("deleteRoute(...)");
00534 
00535     RouteVector::iterator i = std::find(routes.begin(), routes.end(), entry);
00536     if (i!=routes.end())
00537     {
00538         nb->fireChangeNotification(NF_IPv4_ROUTE_DELETED, entry); // rather: going to be deleted
00539         routes.erase(i);
00540         delete entry;
00541         invalidateCache();
00542         updateDisplayString();
00543         generateShowIPRoute();
00544         return true;
00545     }
00546     i = std::find(multicastRoutes.begin(), multicastRoutes.end(), entry);
00547     if (i!=multicastRoutes.end())
00548     {
00549         nb->fireChangeNotification(NF_IPv4_ROUTE_DELETED, entry); // rather: going to be deleted
00550         multicastRoutes.erase(i);
00551         delete entry;
00552         invalidateCache();
00553         updateDisplayString();
00554         generateShowIPRoute();
00555         return true;
00556     }
00557     generateShowIPRoute();
00558     return false;
00559 }
00560 
00561 
00562 bool AnsaRoutingTable::routeMatches(const IPRoute *entry,
00563     const IPAddress& target, const IPAddress& nmask,
00564     const IPAddress& gw, int metric, const char *dev) const
00565 {
00566     if (!target.isUnspecified() && !target.equals(entry->getHost()))
00567         return false;
00568     if (!nmask.isUnspecified() && !nmask.equals(entry->getNetmask()))
00569         return false;
00570     if (!gw.isUnspecified() && !gw.equals(entry->getGateway()))
00571         return false;
00572     if (metric && metric!=entry->getMetric())
00573         return false;
00574     if (dev && strcmp(dev, entry->getInterfaceName()))
00575         return false;
00576 
00577     return true;
00578 }
00579 
00580 void AnsaRoutingTable::updateNetmaskRoutes()
00581 {
00582     // first, delete all routes with src=IFACENETMASK
00583     for (unsigned int k=0; k<routes.size(); k++)
00584         if (routes[k]->getSource()==IPRoute::IFACENETMASK)
00585             routes.erase(routes.begin()+(k--));  // '--' is necessary because indices shift down
00586 
00587     // then re-add them, according to actual interface configuration
00588     for (int i=0; i<ift->getNumInterfaces(); i++)
00589     {
00590         InterfaceEntry *ie = ift->getInterface(i);
00591         if (!ie->isDown())
00592         {
00593           if (ie->ipv4Data()->getNetmask()!=IPAddress::ALLONES_ADDRESS)
00594           {
00595               IPRoute *route = new IPRoute();
00596               route->setType(IPRoute::DIRECT);
00597               route->setSource(IPRoute::IFACENETMASK);
00598               route->setHost((ie->ipv4Data()->getIPAddress()).doAnd(ie->ipv4Data()->getNetmask()));
00599               route->setNetmask(ie->ipv4Data()->getNetmask());
00600               route->setGateway(IPAddress());
00601               route->setMetric(ie->ipv4Data()->getMetric());
00602               route->setInterface(ie);
00603               routes.push_back(route);
00604           }
00605         }
00606     }
00607 
00608     invalidateCache();
00609     updateDisplayString();
00610     generateShowIPRoute();
00611 }
00612 
00613 bool AnsaRoutingTable::checkRoute(const IPRoute* entry)
00614 {
00615   int n = getNumRoutes();
00616   const IPRoute* ipr = NULL;
00617     for (int i=0; i<n; i++)
00618     {
00619       if (matchHostMask(getRoute(i), entry->getHost(), entry->getNetmask()))
00620         ipr=getRoute(i);
00621     }
00622     if (ipr==NULL)
00623       return true;
00624     else
00625     {
00626       if(ADmap.find(entry->getSource())->second < ADmap.find(ipr->getSource())->second)
00627         return true; 
00628     }
00629   return false;    
00630 }
00631 
00632 bool AnsaRoutingTable::matchHostMask(const IPRoute* entry, const IPAddress& target, const IPAddress& nmask)
00633 {
00634   if (!target.isUnspecified() && !target.equals(entry->getHost()))
00635      return false;
00636   if (!nmask.isUnspecified() && !nmask.equals(entry->getNetmask()))
00637      return false;
00638   return true;
00639 }
00640 
00641 void AnsaRoutingTable::generateShowIPRoute()
00642 {
00643   showIPRoute.clear();
00644   
00645   int n = getNumRoutes();
00646   const IPRoute* ipr;
00647     for (int i=0; i<n; i++)
00648     {
00649       ipr=getRoute(i);
00650       switch (ipr->getSource())
00651       {
00652         case IPRoute::MANUAL:
00653           if ((ipr->getMetric())>0)
00654             showIPRoute.push_back(otherIPRouteFormat(ipr));
00655           else
00656             showIPRoute.push_back(directIPRouteFormat(ipr));  
00657           break;          
00658         
00659         case IPRoute::IFACENETMASK:
00660           showIPRoute.push_back(directIPRouteFormat(ipr));
00661           break;
00662         case IPRoute::RIP:
00663          
00664         case IPRoute::OSPF:
00665           
00666         case IPRoute::BGP:
00667          showIPRoute.push_back(otherIPRouteFormat(ipr));         
00668          break;
00669         default: break;
00670       }
00671     } 
00672 }
00673 
00674 std::string AnsaRoutingTable::directIPRouteFormat(const IPRoute* ipr)
00675 {
00676   std::stringstream str;
00677   if ((ipr->getSource())==IPRoute::IFACENETMASK)
00678     str << "C ";
00679   else
00680     str << "S ";
00681     
00682   str << (ipr->getHost()).str();
00683   str << "/";
00684   str << (ipr->getNetmask()).getNetmaskLength();
00685   str << " is directly connected, ";
00686   str << ipr->getInterfaceName();
00687   
00688   return str.str();
00689 }
00690 
00691 std::string AnsaRoutingTable::otherIPRouteFormat(const IPRoute* ipr)
00692 {
00693   std::stringstream str;
00694   switch (ipr->getSource())
00695   {
00696     case IPRoute::RIP:
00697       str << "R ";
00698       break;
00699     case IPRoute::OSPF:
00700       str << "O ";
00701       break;
00702     case IPRoute::BGP:
00703       str << "B ";
00704       break;
00705     case IPRoute::MANUAL:
00706       str << "S ";
00707       break;
00708     default:
00709       break;
00710   }
00711   str << (ipr->getHost()).str();
00712   str << "/";
00713   str << (ipr->getNetmask()).getNetmaskLength();
00714   str << " [";
00715   str << ADmap.find(ipr->getSource())->second;
00716   str << "/";
00717   str << ipr->getMetric();
00718   str << "] via "; 
00719   if ((ipr->getGateway()).isUnspecified())
00720     str << "*";
00721   else
00722     str << (ipr->getGateway()).str();
00723     
00724   return str.str();
00725 }