|
INET Framework for OMNeT++/OMNEST
|
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