IBR-DTNSuite
0.8
|
00001 /* 00002 * LinkManager.cpp 00003 * 00004 * Created on: 21.12.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "ibrcommon/config.h" 00009 #include "ibrcommon/net/LinkManager.h" 00010 #include "ibrcommon/thread/MutexLock.h" 00011 #include <list> 00012 #include <string> 00013 #include <typeinfo> 00014 00015 #ifdef HAVE_LIBNL 00016 #include "ibrcommon/net/NetLinkManager.h" 00017 #else 00018 #ifdef HAVE_LIBNL3 00019 #include "ibrcommon/net/NetLink3Manager.h" 00020 #else 00021 #include <sys/types.h> 00022 #include <netinet/ip.h> 00023 #include <netinet/ip6.h> 00024 #include <arpa/inet.h> 00025 #include <sys/socket.h> 00026 00027 #include <stdlib.h> 00028 #include <net/if.h> 00029 #include <ifaddrs.h> 00030 #include <errno.h> 00031 #include <string.h> 00032 #endif 00033 #endif 00034 00035 namespace ibrcommon 00036 { 00037 LinkManager& LinkManager::getInstance() 00038 { 00039 #ifdef HAVE_LIBNL 00040 static NetLinkManager lm; 00041 #else 00042 #ifdef HAVE_LIBNL3 00043 static NetLink3Manager lm; 00044 #else 00045 static DefaultLinkManager lm; 00046 #endif 00047 #endif 00048 00049 return lm; 00050 } 00051 00052 void LinkManager::initialize() 00053 { 00054 #ifdef HAVE_LIBNL 00055 try { 00056 dynamic_cast<NetLinkManager&>(getInstance()).start(); 00057 } catch (const std::bad_cast&) { }; 00058 #else 00059 #ifdef HAVE_LIBNL3 00060 try { 00061 dynamic_cast<NetLink3Manager&>(getInstance()).start(); 00062 } catch (const std::bad_cast&) { }; 00063 #endif 00064 #endif 00065 } 00066 00067 void LinkManager::registerInterfaceEvent(const vinterface &iface, LinkManager::EventCallback *cb) 00068 { 00069 if (cb == NULL) return; 00070 ibrcommon::MutexLock l(_listener_mutex); 00071 00072 std::set<LinkManager::EventCallback* > &ss = _listener[iface]; 00073 ss.insert(cb); 00074 } 00075 00076 void LinkManager::unregisterInterfaceEvent(const vinterface &iface, LinkManager::EventCallback *cb) 00077 { 00078 if (cb == NULL) return; 00079 ibrcommon::MutexLock l(_listener_mutex); 00080 00081 std::set<LinkManager::EventCallback* > &ss = _listener[iface]; 00082 00083 ss.erase(cb); 00084 00085 if (ss.empty()) 00086 { 00087 _listener.erase(iface); 00088 } 00089 } 00090 00091 void LinkManager::unregisterAllEvents(LinkManager::EventCallback *cb) 00092 { 00093 if (cb == NULL) return; 00094 00095 try { 00096 ibrcommon::MutexLock l(_listener_mutex); 00097 00098 for (std::map<vinterface, std::set<LinkManager::EventCallback* > >::iterator iter = _listener.begin(); iter != _listener.end(); iter++) 00099 { 00100 std::set<LinkManager::EventCallback* > &ss = iter->second; 00101 ss.erase(cb); 00102 } 00103 } catch (const ibrcommon::MutexException&) { 00104 // this happens if this method is called after destroying the object 00105 // and is normal at shutdown 00106 } 00107 } 00108 00109 void LinkManager::raiseEvent(const LinkManagerEvent &lme) 00110 { 00111 // get the corresponding interface 00112 const vinterface &iface = lme.getInterface(); 00113 00114 // search for event subscriptions 00115 ibrcommon::MutexLock l(_listener_mutex); 00116 std::set<LinkManager::EventCallback* > &ss = _listener[iface]; 00117 00118 for (std::set<LinkManager::EventCallback* >::iterator iter = ss.begin(); iter != ss.end(); iter++) 00119 { 00120 try { 00121 (*iter)->eventNotify((LinkManagerEvent&)lme); 00122 } catch (const std::exception&) { }; 00123 } 00124 } 00125 00126 LinkManager::ExternalLinkManagerEvent::ExternalLinkManagerEvent(LinkManagerEvent::EventType type, const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr, unsigned int state) 00127 : _type(type), _iface(iface), _addr(addr), _state(state) 00128 { }; 00129 00130 LinkManager::ExternalLinkManagerEvent::~ExternalLinkManagerEvent() 00131 { }; 00132 00133 const ibrcommon::vinterface& LinkManager::ExternalLinkManagerEvent::getInterface() const 00134 { 00135 return _iface; 00136 }; 00137 00138 const ibrcommon::vaddress& LinkManager::ExternalLinkManagerEvent::getAddress() const 00139 { 00140 return _addr; 00141 }; 00142 00143 unsigned int LinkManager::ExternalLinkManagerEvent::getState() const 00144 { 00145 return _state; 00146 }; 00147 00148 LinkManagerEvent::EventType LinkManager::ExternalLinkManagerEvent::getType() const 00149 { 00150 return _type; 00151 }; 00152 00153 void LinkManager::addressRemoved(const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr) 00154 { 00155 ExternalLinkManagerEvent evt(LinkManagerEvent::EVENT_ADDRESS_REMOVED, iface, addr); 00156 raiseEvent(evt); 00157 } 00158 00159 void LinkManager::addressAdded(const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr) 00160 { 00161 ExternalLinkManagerEvent evt(LinkManagerEvent::EVENT_ADDRESS_ADDED, iface, addr); 00162 raiseEvent(evt); 00163 } 00164 00165 DefaultLinkManager::DefaultLinkManager() 00166 { 00167 } 00168 00169 DefaultLinkManager::~DefaultLinkManager() 00170 { 00171 } 00172 00173 const std::string DefaultLinkManager::getInterface(int index) const 00174 { 00175 #if defined HAVE_LIBNL || HAVE_LIBNL3 00176 throw ibrcommon::Exception("not implemented - use NetlinkManager instead"); 00177 #else 00178 struct ifaddrs *ifap = NULL; 00179 int status = getifaddrs(&ifap); 00180 int i = 0; 00181 std::string ret; 00182 00183 if ((status != 0) || (ifap == NULL)) 00184 { 00185 // error, return with default address 00186 throw ibrcommon::Exception("can not iterate through interfaces"); 00187 } 00188 00189 for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next, i++) 00190 { 00191 if (index == i) 00192 { 00193 ret = iter->ifa_name; 00194 break; 00195 } 00196 } 00197 00198 freeifaddrs(ifap); 00199 00200 return ret; 00201 #endif 00202 } 00203 00204 #if !( defined(HAVE_LIBNL) || defined(HAVE_LIBNL3) ) 00205 char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) 00206 { 00207 switch(sa->sa_family) { 00208 case AF_INET: 00209 inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), 00210 s, maxlen); 00211 break; 00212 00213 case AF_INET6: 00214 inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), 00215 s, maxlen); 00216 break; 00217 00218 default: 00219 strncpy(s, "Unknown AF", maxlen); 00220 return NULL; 00221 } 00222 00223 return s; 00224 } 00225 00226 int get_scope_id(struct sockaddr *sa) 00227 { 00228 switch(sa->sa_family) 00229 { 00230 case AF_INET6: 00231 { 00232 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 00233 return sin6->sin6_scope_id; 00234 } 00235 00236 case AF_INET: 00237 { 00238 return 0; 00239 } 00240 00241 default: 00242 { 00243 return 0; 00244 } 00245 } 00246 } 00247 #endif 00248 00249 const std::list<vaddress> DefaultLinkManager::getAddressList(const vinterface &iface, const vaddress::Family f) 00250 { 00251 std::list<vaddress> ret; 00252 00253 #if !( defined(HAVE_LIBNL) || defined(HAVE_LIBNL3) ) 00254 struct ifaddrs *ifap = NULL; 00255 int status = getifaddrs(&ifap); 00256 int i = 0; 00257 00258 if ((status != 0) || (ifap == NULL)) 00259 { 00260 // error, return with default address 00261 throw ibrcommon::Exception("can not iterate through interfaces"); 00262 } 00263 00264 for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next, i++) 00265 { 00266 if (iter->ifa_addr == NULL) continue; 00267 if ((iter->ifa_flags & IFF_UP) == 0) continue; 00268 00269 // cast to a sockaddr 00270 sockaddr *addr = iter->ifa_addr; 00271 00272 // compare the address family 00273 if ((f != vaddress::VADDRESS_UNSPEC) && (addr->sa_family != f)) continue; 00274 00275 // check the name of the interface 00276 if (string(iter->ifa_name).compare(iface.toString()) != 0) continue; 00277 00278 char buf[INET6_ADDRSTRLEN+5]; 00279 char *name = get_ip_str(iter->ifa_addr, buf, INET6_ADDRSTRLEN+5); 00280 00281 if (name != NULL) 00282 { 00283 std::string name_str(name); 00284 if (get_scope_id(addr) == 0) 00285 { 00286 ret.push_back( 00287 vaddress(vaddress::Family(iter->ifa_addr->sa_family), name_str) 00288 ); 00289 } 00290 else 00291 { 00292 ret.push_back( 00293 vaddress(vaddress::Family(iter->ifa_addr->sa_family), name_str, i) 00294 ); 00295 } 00296 } 00297 00298 00299 } 00300 freeifaddrs(ifap); 00301 #endif 00302 00303 return ret; 00304 } 00305 }