27 #include <netlink/netlink.h>
28 #include <netlink/route/addr.h>
29 #include <netlink/route/link.h>
30 #include <netlink/route/rtnl.h>
31 #include <netlink/socket.h>
32 #include <netlink/msg.h>
33 #include <netlink/object-api.h>
36 #include <sys/socket.h>
37 #include <sys/types.h>
38 #include <netinet/tcp.h>
44 #include <arpa/inet.h>
57 typedef nl_object nl_object_header;
59 struct nl_object_header {
65 struct nl_addr *naddr = rtnl_addr_get_local(obj);
68 int scope = rtnl_addr_get_scope((
struct rtnl_addr *) obj);
71 rtnl_scope2str(scope, scope_buf,
sizeof( scope_buf ));
72 std::string scopename(scope_buf);
74 struct sockaddr_storage sa_addr;
75 socklen_t sa_len =
sizeof(sockaddr_storage);
76 ::memset(&sa_addr, 0, sa_len);
78 if (nl_addr_fill_sockaddr(naddr, (
struct sockaddr*)&sa_addr, &sa_len) < 0) {
83 if (::getnameinfo((
struct sockaddr *) &sa_addr, sa_len, addr_buf,
sizeof addr_buf, NULL, 0, NI_NUMERICHOST) != 0) {
88 std::string addrname(addr_buf);
96 int ifindex = rtnl_addr_get_ifindex((
struct rtnl_addr *) obj);
101 return vaddress(addrname,
"", scopename, sa_addr.ss_family);
105 static void nl_cache_callback(
struct nl_cache*,
struct nl_object *obj,
int action,
void*)
107 static void nl_cache_callback(
struct nl_cache*,
struct nl_object *obj,
int action)
110 if (obj == NULL)
return;
113 nl_object_header *header =
static_cast<nl_object_header*
>(nl_object_priv(obj));
115 switch (header->ce_msgtype) {
119 struct rtnl_link *link = (
struct rtnl_link *) obj;
121 int ifindex = rtnl_link_get_ifindex(link);
124 struct nl_addr *naddr = rtnl_link_get_addr(link);
131 nl_addr2str( naddr, addr_buf,
sizeof( addr_buf ));
132 std::string addrname(addr_buf);
134 addr = vaddress(addrname,
"", static_cast<sa_family_t>(nl_addr_guess_family(naddr)));
137 unsigned int flags = rtnl_link_get_flags(link);
139 if (flags & IFF_RUNNING) {
141 }
else if (flags & IFF_UP) {
147 LinkEvent lme(evt_action, iface, addr);;
156 if (action == NL_ACT_NEW)
158 else if (action == NL_ACT_DEL)
161 int ifindex = rtnl_addr_get_ifindex((
struct rtnl_addr *) obj);
166 LinkEvent lme(evt_action, iface, addr);;
174 struct nl_dump_params dp;
175 memset(&dp, 0,
sizeof(
struct nl_dump_params));
177 dp.dp_type = NL_DUMP_LINE;
179 dp.dp_type = NL_DUMP_BRIEF;
182 nl_object_dump(obj, &dp);
190 std::list<vaddress> *list =
static_cast<std::list<vaddress>*
>(data);
195 list->push_back( addr );
200 NetLinkManager::netlinkcache::netlinkcache(
int protocol)
201 : _protocol(protocol), _nl_handle(NULL), _mngr(NULL)
205 NetLinkManager::netlinkcache::~netlinkcache()
209 void NetLinkManager::netlinkcache::up() throw (socket_exception)
211 if (_state != SOCKET_DOWN)
212 throw socket_exception(
"socket is already up");
217 _nl_handle = nl_socket_alloc();
219 _nl_handle = nl_handle_alloc();
224 ret = nl_cache_mngr_alloc((
struct nl_sock*)_nl_handle, _protocol, NL_AUTO_PROVIDE, &_mngr);
227 throw socket_exception(
"can not allocate netlink cache manager");
229 _mngr = nl_cache_mngr_alloc((
struct nl_handle*)_nl_handle, _protocol, NL_AUTO_PROVIDE);
233 throw socket_exception(
"can not allocate netlink cache manager");
235 for (std::map<std::string, struct nl_cache*>::iterator iter = _caches.begin(); iter != _caches.end(); ++iter)
237 const std::string &cachename = (*iter).first;
240 ret = nl_cache_mngr_add(_mngr, cachename.c_str(), &nl_cache_callback,
this, &c);
243 throw socket_exception(std::string(
"can not allocate netlink cache ") + cachename);
245 struct nl_cache *c = nl_cache_mngr_add(_mngr, cachename.c_str(), &nl_cache_callback);
249 throw socket_exception(std::string(
"can not allocate netlink cache ") + cachename);
258 void NetLinkManager::netlinkcache::down() throw (socket_exception)
260 if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
261 throw socket_exception(
"socket is not up");
264 nl_cache_mngr_free(_mngr);
268 nl_socket_free((
struct nl_sock*)_nl_handle);
272 if (_state == SOCKET_UNMANAGED)
273 _state = SOCKET_DESTROYED;
275 _state = SOCKET_DOWN;
278 int NetLinkManager::netlinkcache::fd()
const throw (socket_exception)
280 if (_state == SOCKET_DOWN)
throw socket_exception(
"fd not available");
281 return nl_cache_mngr_get_fd(_mngr);
284 void NetLinkManager::netlinkcache::receive() throw (socket_exception)
286 if (_state == SOCKET_DOWN)
throw socket_exception(
"socket not connected");
287 nl_cache_mngr_data_ready(_mngr);
289 int ret = nl_cache_mngr_data_ready(_mngr);
297 throw socket_exception(
"can not receive data from netlink manager");
301 void NetLinkManager::netlinkcache::add(
const std::string &cachename)
throw (socket_exception)
303 if (_state != SOCKET_DOWN)
304 throw socket_exception(
"socket is already up; adding not possible");
306 std::map<std::string, struct nl_cache*>::const_iterator iter = _caches.find(cachename);
307 if (iter != _caches.end())
throw socket_exception(
"cache already added");
310 _caches[cachename] = NULL;
313 struct nl_cache* NetLinkManager::netlinkcache::get(
const std::string &cachename)
const throw (socket_exception)
315 if (_state == SOCKET_DOWN)
throw socket_exception(
"socket not available");
317 std::map<std::string, struct nl_cache*>::const_iterator iter = _caches.find(cachename);
318 if (iter == _caches.end())
throw socket_exception(
"cache not available");
320 return (*iter).second;
323 NetLinkManager::NetLinkManager()
324 : _route_cache(NETLINK_ROUTE),
_running(true)
327 _route_cache.add(
"route/link");
328 _route_cache.add(
"route/addr");
334 NetLinkManager::~NetLinkManager()
341 }
catch (
const socket_exception&) {
347 void NetLinkManager::up() throw ()
350 _sock.add(&_route_cache);
356 void NetLinkManager::down() throw ()
365 void NetLinkManager::__cancellation() throw ()
371 void NetLinkManager::run() throw ()
377 _sock.select(&socks, NULL, NULL, NULL);
379 for (socketset::iterator iter = socks.begin(); iter != socks.end(); ++iter) {
381 netlinkcache &cache =
dynamic_cast<netlinkcache&
>(**iter);
383 }
catch (
const bad_cast&) { };
386 }
catch (
const socket_exception&) {
392 const std::list<vaddress> NetLinkManager::getAddressList(
const vinterface &iface,
const std::string &scope)
396 std::list<vaddress> addresses;
398 struct rtnl_addr *filter = rtnl_addr_alloc();
399 const std::string i = iface.
toString();
400 int ifindex = rtnl_link_name2i(_route_cache.get(
"route/link"), i.c_str());
402 rtnl_addr_set_ifindex(filter, ifindex);
405 if (scope.length() > 0) {
406 rtnl_addr_set_scope(filter, rtnl_str2scope(scope.c_str()));
410 nl_cache_foreach_filter(_route_cache.get(
"route/addr"), (
struct nl_object *) filter,
add_addr_to_list, &addresses);
413 rtnl_addr_put(filter);
418 const vinterface NetLinkManager::getInterface(
const int ifindex)
const
421 rtnl_link_i2name(_route_cache.get(
"route/link"), ifindex, (
char*)&buf,
sizeof buf);
422 return std::string((
char*)&buf);