IBR-DTNSuite  0.8
ibrcommon/ibrcommon/net/LinkManager.cpp
Go to the documentation of this file.
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 }