NetworkInfo.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2007 Vojtech Janota
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include <fstream>
00019 #include <algorithm>
00020 
00021 #include "NetworkInfo.h"
00022 #include "IRoutingTable.h"
00023 #include "IPAddressResolver.h"
00024 #include "InterfaceEntry.h"
00025 
00026 
00027 Define_Module(NetworkInfo);
00028 
00029 void NetworkInfo::initialize()
00030 {
00031     // so far no initialization
00032 }
00033 
00034 void NetworkInfo::handleMessage(cMessage *msg)
00035 {
00036     ASSERT(false);
00037 }
00038 
00039 void NetworkInfo::processCommand(const cXMLElement& node)
00040 {
00041     cModule *target = simulation.getModuleByPath(node.getAttribute("target"));
00042 
00043     if (!strcmp(node.getTagName(), "routing"))
00044     {
00045         const char *filename = node.getAttribute("file");
00046         ASSERT(filename);
00047         const char *mode = node.getAttribute("mode");
00048         const char *compat = node.getAttribute("compat");
00049 
00050         dumpRoutingInfo(target, filename, (mode && !strcmp(mode, "a")), (compat && !strcmp(compat, "linux")));
00051     }
00052     else
00053         ASSERT(false);
00054 }
00055 
00056 void NetworkInfo::dumpRoutingInfo(cModule *target, const char *filename, bool append, bool compat)
00057 {
00058     std::ofstream s;
00059     s.open(filename, append?(std::ios::app):(std::ios::out));
00060     if (s.fail())
00061         error("cannot open `%s' for write", filename);
00062 
00063     if (compat) s << "Kernel IP routing table" << endl;
00064     s << "Destination     Gateway         Genmask         ";
00065     if (compat) s << "Flags ";
00066     s << "Metric ";
00067     if (compat) s << "Ref    Use ";
00068     s << "Iface" << endl;
00069 
00070     cModule *rtmod = target->getSubmodule("routingTable");
00071     if (rtmod)
00072     {
00073         std::vector<std::string> lines;
00074 
00075         IRoutingTable *rt = check_and_cast<IRoutingTable *>(rtmod);
00076         for (int i = 0; i < rt->getNumRoutes(); i++)
00077         {
00078             IPAddress host = rt->getRoute(i)->getHost();
00079 
00080             if (host.isMulticast())
00081                 continue;
00082 
00083             if (rt->getRoute(i)->getInterface()->isLoopback())
00084                 continue;
00085 
00086             IPAddress netmask = rt->getRoute(i)->getNetmask();
00087             IPAddress gateway = rt->getRoute(i)->getGateway();
00088             int metric = rt->getRoute(i)->getMetric();
00089 
00090             std::ostringstream line;
00091 
00092             line << std::left;
00093             IPAddress dest = compat ? host.doAnd(netmask) : host;
00094             line.width(16);
00095             if (dest.isUnspecified()) line << "0.0.0.0"; else line << dest;
00096 
00097             line.width(16);
00098             if (gateway.isUnspecified()) line << "0.0.0.0"; else line << gateway;
00099 
00100             line.width(16);
00101             if (netmask.isUnspecified()) line << "0.0.0.0"; else line << netmask;
00102 
00103             if (compat)
00104             {
00105                 int pad = 3;
00106                 line << "U"; // routes in INET are always up
00107                 if (!gateway.isUnspecified()) line << "G"; else ++pad;
00108                 if (netmask.equals(IPAddress::ALLONES_ADDRESS)) line << "H"; else ++pad;
00109                 line.width(pad);
00110                 line << " ";
00111             }
00112 
00113             line.width(7);
00114             if (compat && rt->getRoute(i)->getSource() == IPRoute::IFACENETMASK)
00115                 metric = 0;
00116             line << metric;
00117 
00118             if (compat) line << "0        0 ";
00119 
00120             line << rt->getRoute(i)->getInterfaceName() << endl;
00121 
00122             if (compat)
00123                 lines.push_back(line.str());
00124             else
00125                 s << line.str();
00126         }
00127 
00128         if (compat)
00129         {
00130             // sort to avoid random order
00131             // typically routing tables are sorted by netmask prefix length (descending)
00132             // sorting by reversed natural order looks weired, but allows easy comparison
00133             // with `route -n | sort -r` output by means of `diff` command...
00134             std::sort(lines.begin(), lines.end());
00135             for (std::vector<std::string>::reverse_iterator it = lines.rbegin(); it != lines.rend(); it++)
00136                 s << *it;
00137         }
00138     }
00139     s << endl;
00140     s.close();
00141 }