00001
00002
00003
00004
00005
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
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
00221
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
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
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
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 }