• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

ibrcommon/ibrcommon/net/NetInterface.cpp

Go to the documentation of this file.
00001 /*
00002  * File:   NetInterface.cpp
00003  * Author: morgenro
00004  *
00005  * Created on 12. November 2009, 14:57
00006  */
00007 
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/net/NetInterface.h"
00010 #include "ibrcommon/thread/MutexLock.h"
00011 #include "ibrcommon/Exceptions.h"
00012 
00013 #include <sys/types.h>
00014 #include <netinet/in.h>
00015 #include <netinet/ip.h>
00016 #include <netinet/ip6.h>
00017 #include <arpa/inet.h>
00018 #include <sys/socket.h>
00019 
00020 #include <stdlib.h>
00021 #include <net/if.h>
00022 
00023 #ifdef HAVE_LIBNL
00024 #include <netlink/route/link.h>
00025 #include <netlink/route/addr.h>
00026 #include <netlink/genl/genl.h>
00027 #include <netlink/genl/ctrl.h>
00028 #endif
00029 
00030 #include <errno.h>
00031 
00032 #ifdef HAVE_LOWPAN_SUPPORT
00033 extern "C" {
00034 #include "ibrcommon/net/ieee802154.h"
00035 #include "ibrcommon/net/nl802154.h"
00036 extern struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1];
00037 };
00038 #endif
00039 
00040 #include <unistd.h>
00041 
00042 using namespace std;
00043 
00044 namespace ibrcommon
00045 {
00046 #ifdef HAVE_LIBNL
00047 void add_addr_to_list(struct nl_object *obj, void *data)
00048 {
00049         char buf[INET6_ADDRSTRLEN + 1];
00050         std::list<NetAddress> *list = static_cast<std::list<NetAddress>*>(data);
00051 
00052     struct nl_addr *naddr =
00053         rtnl_addr_get_local((struct rtnl_addr *) obj);
00054     int family = nl_addr_get_family(naddr);
00055 
00056     if (family == AF_INET6)
00057     {
00058         struct in6_addr *tmpaddr = (struct in6_addr *) nl_addr_get_binary_addr(naddr);
00059 
00060         if (inet_ntop (AF_INET6, tmpaddr, buf, sizeof (buf)))
00061         {
00062                 list->push_back( NetAddress(NetAddress::NETADDR_IP6, buf, nl_addr_get_prefixlen(naddr)) );
00063         }
00064     }
00065     else if (family == AF_INET)
00066     {
00067         struct in_addr *tmpaddr = (struct in_addr *) nl_addr_get_binary_addr(naddr);
00068 
00069         if (inet_ntop (AF_INET, tmpaddr, buf, sizeof (buf)))
00070         {
00071                 list->push_back( NetAddress(NetAddress::NETADDR_IP, buf, nl_addr_get_prefixlen(naddr)) );
00072         }
00073     }
00074 }
00075 
00076 void add_broadcast_addr_to_list(struct nl_object *obj, void *data)
00077 {
00078         char buf[INET6_ADDRSTRLEN + 1];
00079         std::list<NetAddress> *list = static_cast<std::list<NetAddress>*>(data);
00080 
00081         struct nl_addr *naddr = rtnl_addr_get_local((struct rtnl_addr *) obj);
00082         int family = nl_addr_get_family(naddr);
00083 
00084         struct nl_addr *baddr = rtnl_addr_get_broadcast((struct rtnl_addr *) obj);
00085 
00086         if (baddr)
00087         {
00088                 nl_addr2str( baddr, buf, sizeof( buf ) );
00089 
00090                 if (family == AF_INET6)
00091                 {
00092                         list->push_back( NetAddress(NetAddress::NETADDR_IP6, buf, nl_addr_get_prefixlen(baddr)) );
00093                 }
00094                 else if (family == AF_INET)
00095                 {
00096                         list->push_back( NetAddress(NetAddress::NETADDR_IP, buf, nl_addr_get_prefixlen(baddr)) );
00097                 }
00098         }
00099 }
00100 #endif
00101 
00102         // static initialization
00103         NetInterface::NetLinkWrapper NetInterface::_nlwrapper;
00104 
00105         NetInterface::NetLinkWrapper::NetLinkWrapper()
00106         {
00107                 _handle = nl_handle_alloc();
00108                 nl_connect(_handle, NETLINK_ROUTE);
00109 
00110                 _link_cache = rtnl_link_alloc_cache(_handle);
00111                 _addr_cache = rtnl_addr_alloc_cache(_handle);
00112         }
00113 
00114         NetInterface::NetLinkWrapper::~NetLinkWrapper()
00115         {
00116                 nl_cache_free(_addr_cache);
00117                 nl_cache_free(_link_cache);
00118                 nl_handle_destroy(_handle);
00119         }
00120 
00121         const std::list<NetAddress> NetInterface::NetLinkWrapper::getAddressList(const std::string interface) const
00122         {
00123                 ibrcommon::MutexLock l(_mutex);
00124                 std::list<NetAddress> addresses;
00125 
00126                 struct rtnl_addr *filter = rtnl_addr_alloc();
00127                 rtnl_addr_set_ifindex(filter, rtnl_link_name2i(_link_cache, interface.c_str()));
00128 
00129                 rtnl_addr_set_family(filter, AF_INET6);
00130                 nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
00131                                                                 add_addr_to_list, &addresses);
00132 
00133                 rtnl_addr_set_family(filter, AF_INET);
00134                 nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
00135                                                                 add_addr_to_list, &addresses);
00136 
00137                 rtnl_addr_put(filter);
00138 
00139                 return addresses;
00140         }
00141 
00142         const std::list<NetAddress> NetInterface::NetLinkWrapper::getBroadcastList(const std::string interface) const
00143         {
00144                 ibrcommon::MutexLock l(_mutex);
00145                 std::list<NetAddress> addresses;
00146 
00147                 struct rtnl_addr *filter = rtnl_addr_alloc();
00148                 rtnl_addr_set_ifindex(filter, rtnl_link_name2i(_link_cache, interface.c_str()));
00149 
00150                 rtnl_addr_set_family(filter, AF_INET6);
00151                 nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
00152                                                                 add_broadcast_addr_to_list, &addresses);
00153 
00154                 rtnl_addr_set_family(filter, AF_INET);
00155                 nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
00156                                                                 add_broadcast_addr_to_list, &addresses);
00157 
00158                 rtnl_addr_put(filter);
00159 
00160                 return addresses;
00161         }
00162 
00163         NetInterface::NetInterface(std::string interface)
00164         : _interface(interface)
00165         {
00166         }
00167 
00168         NetInterface::~NetInterface()
00169         {
00170         }
00171 
00172         bool NetInterface::operator<(const NetInterface &other) const
00173         {
00174                 if (_interface < other._interface) return true;
00175                 return false;
00176         }
00177 
00178         bool NetInterface::operator==(const NetInterface &other) const
00179         {
00180                 if (_interface == other._interface) return true;
00181                 return false;
00182         }
00183 
00184         const std::string NetInterface::toString() const
00185         {
00186                 return _interface;
00187         }
00188 
00189         const std::list<NetAddress> NetInterface::getAddressList() const
00190         {
00191                 return _nlwrapper.getAddressList(_interface);
00192         }
00193 
00194         const NetAddress NetInterface::getAddress(const NetAddress::ADDR_TYPE type) const
00195         {
00196                 std::list<NetAddress> list = getAddressList();
00197 
00198                 for (std::list<NetAddress>::const_iterator iter = list.begin(); iter != list.end(); iter++)
00199                 {
00200                         if (iter->type == type)
00201                         {
00202                                 return (*iter);
00203                         }
00204                 }
00205 
00206                 throw ibrcommon::Exception("no address found");
00207         }
00208 
00209         void NetInterface::getAddress(struct in_addr *ret) const
00210         {
00211                 NetAddress addr = getAddress(NetAddress::NETADDR_IP);
00212                 inet_aton(addr.toString().c_str(), ret);
00213         }
00214 
00215         const std::string NetInterface::getAddress() const
00216         {
00217                 return getAddress(NetAddress::NETADDR_IP).toString();
00218         }
00219 
00220         /* The Linux MAC802152 stack speaks netlink to userspace. Use it to get
00221          * the current address and PAN ID */
00222         void NetInterface::getAddress(struct ieee802154_addr *ret) const
00223         {
00224 #ifdef HAVE_LOWPAN_SUPPORT
00225                 struct nl_handle *nl = nl_handle_alloc();
00226                 unsigned char *buf = NULL;
00227                 struct sockaddr_nl nla;
00228                 struct nlattr *attrs[IEEE802154_ATTR_MAX+1];
00229                 struct genlmsghdr *ghdr;
00230                 struct nlmsghdr *nlh;
00231                 struct nl_msg *msg;
00232                 int family;
00233 
00234                 if (!nl)
00235                         return;
00236 
00237                 genl_connect(nl);
00238 
00239                 /* Build and send message */
00240                 msg = nlmsg_alloc();
00241                 family = genl_ctrl_resolve(nl, "802.15.4 MAC");
00242                 genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, IEEE802154_LIST_IFACE, 1);
00243                 nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, _interface.c_str());
00244                 nl_send_auto_complete(nl, msg);
00245                 nlmsg_free(msg);
00246 
00247                 /* Receive and parse answer */
00248                 nl_recv(nl, &nla, &buf, NULL);
00249                 nlh = (struct nlmsghdr*)buf;
00250                 genlmsg_parse(nlh, 0, attrs, IEEE802154_ATTR_MAX, ieee802154_policy);
00251                 ghdr = (genlmsghdr*)nlmsg_data(nlh);
00252                 if (!attrs[IEEE802154_ATTR_SHORT_ADDR] || !attrs[IEEE802154_ATTR_SHORT_ADDR])
00253                         return;
00254 
00255                 // We only handle short addresses right now
00256                 ret->addr_type = IEEE802154_ADDR_SHORT;
00257                 ret->pan_id = nla_get_u16(attrs[IEEE802154_ATTR_PAN_ID]);
00258                 ret->short_addr = nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]);
00259 
00260                 free(buf);
00261                 nl_close(nl);
00262 #endif
00263         }
00264 
00265         const NetAddress NetInterface::getBroadcast(const NetAddress::ADDR_TYPE type) const
00266         {
00267                 std::list<NetAddress> list = getBroadcastList();
00268 
00269                 for (std::list<NetAddress>::const_iterator iter = list.begin(); iter != list.end(); iter++)
00270                 {
00271                         if (iter->type == type)
00272                         {
00273                                 return (*iter);
00274                         }
00275                 }
00276 
00277                 throw ibrcommon::Exception("no address found");
00278         }
00279 
00280         const std::list<NetAddress> NetInterface::getBroadcastList() const
00281         {
00282                 return _nlwrapper.getBroadcastList(_interface);
00283         }
00284 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1