IPAddressResolver.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 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 Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 
00019 #include "IPAddressResolver.h"
00020 #include "IInterfaceTable.h"
00021 #include "IPv4InterfaceData.h"
00022 #include "IRoutingTable.h"
00023 #include "NotificationBoard.h"
00024 #ifndef WITHOUT_IPv6
00025 #include "IPv6InterfaceData.h"
00026 #include "RoutingTable6.h"
00027 #endif
00028 
00029 
00030 IPvXAddress IPAddressResolver::resolve(const char *s, int addrType)
00031 {
00032     IPvXAddress addr;
00033     if (!tryResolve(s, addr, addrType))
00034         opp_error("IPAddressResolver: address `%s' not configured (yet?)", s);
00035     return addr;
00036 }
00037 
00038 bool IPAddressResolver::tryResolve(const char *s, IPvXAddress& result, int addrType)
00039 {
00040     // empty address
00041     result = IPvXAddress();
00042     if (!s || !*s)
00043         return true;
00044 
00045     // handle address literal
00046     if (result.tryParse(s))
00047         return true;
00048 
00049     // must be "modulename/interfacename(protocol)" syntax then,
00050     // "/interfacename" and "(protocol)" being optional
00051     const char *slashp = strchr(s,'/');
00052     const char *leftparenp = strchr(s,'(');
00053     const char *rightparenp = strchr(s,')');
00054     const char *endp = s+strlen(s);
00055 
00056     // rudimentary syntax check
00057     if ((slashp && leftparenp && slashp>leftparenp) ||
00058         (leftparenp && !rightparenp) ||
00059         (!leftparenp && rightparenp) ||
00060         (rightparenp && rightparenp!=endp-1))
00061     {
00062         opp_error("IPAddressResolver: syntax error parsing address spec `%s'", s);
00063     }
00064 
00065     // parse fields: modname, ifname, protocol
00066     std::string modname, ifname, protocol;
00067     modname.assign(s, (slashp?slashp:leftparenp?leftparenp:endp)-s);
00068     if (slashp)
00069         ifname.assign(slashp+1, (leftparenp?leftparenp:endp)-slashp-1);
00070     if (leftparenp)
00071         protocol.assign(leftparenp+1, rightparenp-leftparenp-1);
00072 
00073     // find module and check protocol
00074     cModule *mod = simulation.getModuleByPath(modname.c_str());
00075     if (!mod)
00076         opp_error("IPAddressResolver: module `%s' not found", modname.c_str());
00077     if (!protocol.empty() && protocol!="ipv4" && protocol!="ipv6")
00078         opp_error("IPAddressResolver: error parsing address spec `%s': address type must be `(ipv4)' or `(ipv6)'", s);
00079     if (!protocol.empty())
00080         addrType = protocol=="ipv4" ? ADDR_IPv4 : ADDR_IPv6;
00081 
00082     // get address from the given module/interface
00083     if (ifname.empty())
00084         result = addressOf(mod, addrType);
00085     else if (ifname == "routerId")
00086         result = IPvXAddress(routerIdOf(mod)); // addrType is meaningless here, routerId is protocol independent
00087     else
00088         result = addressOf(mod, ifname.c_str(), addrType);
00089     return !result.isUnspecified();
00090 }
00091 
00092 IPAddress IPAddressResolver::routerIdOf(cModule *host)
00093 {
00094     IRoutingTable *rt = routingTableOf(host);
00095     return rt->getRouterId();
00096 }
00097 
00098 IPvXAddress IPAddressResolver::addressOf(cModule *host, int addrType)
00099 {
00100     IInterfaceTable *ift = interfaceTableOf(host);
00101     return getAddressFrom(ift, addrType);
00102 }
00103 
00104 IPvXAddress IPAddressResolver::addressOf(cModule *host, const char *ifname, int addrType)
00105 {
00106     IInterfaceTable *ift = interfaceTableOf(host);
00107     InterfaceEntry *ie = ift->getInterfaceByName(ifname);
00108     if (!ie)
00109         opp_error("IPAddressResolver: no interface called `%s' in interface table", ifname, ift->getFullPath().c_str());
00110     return getAddressFrom(ie, addrType);
00111 }
00112 
00113 IPvXAddress IPAddressResolver::getAddressFrom(IInterfaceTable *ift, int addrType)
00114 {
00115     IPvXAddress ret;
00116     if (addrType==ADDR_IPv6 || addrType==ADDR_PREFER_IPv6)
00117     {
00118         ret = getIPv6AddressFrom(ift);
00119         if (ret.isUnspecified() && addrType==ADDR_PREFER_IPv6)
00120             ret = getIPv4AddressFrom(ift);
00121     }
00122     else if (addrType==ADDR_IPv4 || addrType==ADDR_PREFER_IPv4)
00123     {
00124         ret = getIPv4AddressFrom(ift);
00125         if (ret.isUnspecified() && addrType==ADDR_PREFER_IPv4)
00126             ret = getIPv6AddressFrom(ift);
00127     }
00128     else
00129     {
00130         opp_error("IPAddressResolver: unknown addrType %d", addrType);
00131     }
00132     return ret;
00133 }
00134 
00135 IPvXAddress IPAddressResolver::getAddressFrom(InterfaceEntry *ie, int addrType)
00136 {
00137     IPvXAddress ret;
00138     if (addrType==ADDR_IPv6 || addrType==ADDR_PREFER_IPv6)
00139     {
00140         if (ie->ipv6Data())
00141             ret = getInterfaceIPv6Address(ie);
00142         if (ret.isUnspecified() && addrType==ADDR_PREFER_IPv6 && ie->ipv4Data())
00143             ret = ie->ipv4Data()->getIPAddress();
00144     }
00145     else if (addrType==ADDR_IPv4 || addrType==ADDR_PREFER_IPv4)
00146     {
00147         if (ie->ipv4Data())
00148             ret = ie->ipv4Data()->getIPAddress();
00149         if (ret.isUnspecified() && addrType==ADDR_PREFER_IPv4 && ie->ipv6Data())
00150             ret = getInterfaceIPv6Address(ie);
00151     }
00152     else
00153     {
00154         opp_error("IPAddressResolver: unknown addrType %d", addrType);
00155     }
00156     return ret;
00157 }
00158 
00159 IPAddress IPAddressResolver::getIPv4AddressFrom(IInterfaceTable *ift)
00160 {
00161     IPAddress addr;
00162     if (ift->getNumInterfaces()==0)
00163         opp_error("IPAddressResolver: interface table `%s' has no interface registered "
00164                   "(yet? try in a later init stage!)", ift->getFullPath().c_str());
00165 
00166     // choose first usable interface address (configured for IPv4, non-loopback if, addr non-null)
00167     for (int i=0; i<ift->getNumInterfaces(); i++)
00168     {
00169         InterfaceEntry *ie = ift->getInterface(i);
00170         if (ie->ipv4Data() && !ie->ipv4Data()->getIPAddress().isUnspecified() && !ie->isLoopback())
00171         {
00172             addr = ie->ipv4Data()->getIPAddress();
00173             break;
00174         }
00175     }
00176     return addr;
00177 }
00178 
00179 IPv6Address IPAddressResolver::getIPv6AddressFrom(IInterfaceTable *ift)
00180 {
00181 #ifndef WITHOUT_IPv6
00182     // browse interfaces and pick a globally routable address
00183     if (ift->getNumInterfaces()==0)
00184         opp_error("IPAddressResolver: interface table `%s' has no interface registered "
00185                   "(yet? try in a later init stage!)", ift->getFullPath().c_str());
00186 
00187     IPv6Address addr;
00188     for (int i=0; i<ift->getNumInterfaces() && addr.isUnspecified(); i++)
00189     {
00190         InterfaceEntry *ie = ift->getInterface(i);
00191         if (!ie->ipv6Data() || ie->isLoopback())
00192             continue;
00193         IPv6Address ifAddr = ie->ipv6Data()->getPreferredAddress();
00194         if (addr.isGlobal() && ifAddr.isGlobal() && addr!=ifAddr)
00195             EV << ift->getFullPath() << " has at least two globally routable addresses on different interfaces\n";
00196         if (ifAddr.isGlobal())
00197             addr = ifAddr;
00198     }
00199     return addr;
00200 #else
00201     return IPv6Address();
00202 #endif
00203 }
00204 
00205 IPv6Address IPAddressResolver::getInterfaceIPv6Address(InterfaceEntry *ie)
00206 {
00207 #ifndef WITHOUT_IPv6
00208     if (!ie->ipv6Data())
00209         return IPv6Address();
00210     return ie->ipv6Data()->getPreferredAddress();
00211 #else
00212     return IPv6Address();
00213 #endif
00214 }
00215 
00216 IInterfaceTable *IPAddressResolver::interfaceTableOf(cModule *host)
00217 {
00218     // find IInterfaceTable
00219     cModule *mod = host->getSubmodule("interfaceTable");
00220     if (!mod)
00221         opp_error("IPAddressResolver: IInterfaceTable not found as submodule "
00222                   " `interfaceTable' in host/router `%s'", host->getFullPath().c_str());
00223     return check_and_cast<IInterfaceTable *>(mod);
00224 }
00225 
00226 IRoutingTable *IPAddressResolver::routingTableOf(cModule *host)
00227 {
00228     // find IRoutingTable
00229     cModule *mod = host->getSubmodule("routingTable");
00230     if (!mod)
00231         opp_error("IPAddressResolver: IRoutingTable not found as submodule "
00232                   " `routingTable' in host/router `%s'", host->getFullPath().c_str());
00233     return check_and_cast<IRoutingTable *>(mod);
00234 }
00235 
00236 #ifndef WITHOUT_IPv6
00237 RoutingTable6 *IPAddressResolver::routingTable6Of(cModule *host)
00238 {
00239     // find IRoutingTable
00240     cModule *mod = host->getSubmodule("routingTable6");
00241     if (!mod)
00242         opp_error("IPAddressResolver: RoutingTable6 not found as submodule "
00243                   " `routingTable6' in host/router `%s'", host->getFullPath().c_str());
00244     return check_and_cast<RoutingTable6 *>(mod);
00245 }
00246 #endif
00247 
00248 NotificationBoard *IPAddressResolver::notificationBoardOf(cModule *host)
00249 {
00250     // find NotificationBoard
00251     cModule *mod = host->getSubmodule("notificationBoard");
00252     if (!mod)
00253         opp_error("IPAddressResolver: NotificationBoard not found as submodule "
00254                   " notificationBoard' in host/router `%s'", host->getFullPath().c_str());
00255     return check_and_cast<NotificationBoard *>(mod);
00256 }
00257 
00258 IInterfaceTable *IPAddressResolver::findInterfaceTableOf(cModule *host)
00259 {
00260     cModule *mod = host->getSubmodule("interfaceTable");
00261     return dynamic_cast<IInterfaceTable *>(mod);
00262 }
00263 
00264 IRoutingTable *IPAddressResolver::findRoutingTableOf(cModule *host)
00265 {
00266     cModule *mod = host->getSubmodule("routingTable");
00267     return dynamic_cast<IRoutingTable *>(mod);
00268 }
00269 
00270 #ifndef WITHOUT_IPv6
00271 RoutingTable6 *IPAddressResolver::findRoutingTable6Of(cModule *host)
00272 {
00273     cModule *mod = host->getSubmodule("routingTable6");
00274     return dynamic_cast<RoutingTable6 *>(mod);
00275 }
00276 #endif
00277 
00278 NotificationBoard *IPAddressResolver::findNotificationBoardOf(cModule *host)
00279 {
00280     cModule *mod = host->getSubmodule("notificationBoard");
00281     return dynamic_cast<NotificationBoard *>(mod);
00282 }
00283 
00284 
00285 
00286