27 #include <netlink/object-api.h>
28 #include <netlink/cache-api.h>
29 #include <netlink/route/link.h>
30 #include <netlink/route/addr.h>
31 #include <netlink/route/rtnl.h>
33 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
34 #include <netlink/version.h>
38 #include <sys/socket.h>
39 #include <sys/types.h>
40 #include <netinet/tcp.h>
46 #include <arpa/inet.h>
64 return static_cast<__nl_object*
>(nl_object_priv(obj))->ce_msgtype;
67 #if LIBNL_CURRENT < 206
71 return static_cast<nl_object*
>(nl_object_priv(obj))->ce_msgtype;
77 struct nl_addr *naddr = rtnl_addr_get_local(obj);
80 int scope = rtnl_addr_get_scope((
struct rtnl_addr *) obj);
83 rtnl_scope2str(scope, scope_buf,
sizeof( scope_buf ));
84 std::string scopename(scope_buf);
86 struct sockaddr_storage sa_addr;
87 socklen_t sa_len =
sizeof(sockaddr_storage);
88 ::memset(&sa_addr, 0, sa_len);
90 if (nl_addr_fill_sockaddr(naddr, (
struct sockaddr*)&sa_addr, &sa_len) < 0) {
95 if (::getnameinfo((
struct sockaddr *) &sa_addr, sa_len, addr_buf,
sizeof addr_buf, NULL, 0, NI_NUMERICHOST) != 0) {
100 std::string addrname(addr_buf);
108 int ifindex = rtnl_addr_get_ifindex((
struct rtnl_addr *) obj);
113 return vaddress(addrname,
"", scopename, sa_addr.ss_family);
116 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
117 static void nl_cache_callback(
struct nl_cache*,
struct nl_object *obj,
int action,
void*)
119 static void nl_cache_callback(
struct nl_cache*,
struct nl_object *obj,
int action)
122 if (obj == NULL)
return;
128 struct rtnl_link *link = (
struct rtnl_link *) obj;
130 int ifindex = rtnl_link_get_ifindex(link);
133 struct nl_addr *naddr = rtnl_link_get_addr(link);
140 nl_addr2str( naddr, addr_buf,
sizeof( addr_buf ));
141 std::string addrname(addr_buf);
143 addr = vaddress(addrname,
"", static_cast<sa_family_t>(nl_addr_guess_family(naddr)));
146 unsigned int flags = rtnl_link_get_flags(link);
148 if (flags & IFF_RUNNING) {
150 }
else if (flags & IFF_UP) {
156 LinkEvent lme(evt_action, iface, addr);;
162 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
165 if (action == NL_ACT_NEW)
167 else if (action == NL_ACT_DEL)
170 int ifindex = rtnl_addr_get_ifindex((
struct rtnl_addr *) obj);
175 LinkEvent lme(evt_action, iface, addr);;
183 struct nl_dump_params dp;
184 memset(&dp, 0,
sizeof(
struct nl_dump_params));
185 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
186 dp.dp_type = NL_DUMP_LINE;
188 dp.dp_type = NL_DUMP_BRIEF;
191 nl_object_dump(obj, &dp);
199 std::list<vaddress> *list =
static_cast<std::list<vaddress>*
>(data);
204 list->push_back( addr );
209 NetLinkManager::netlinkcache::netlinkcache(
int protocol)
210 : _protocol(protocol), _nl_handle(NULL), _mngr(NULL)
214 NetLinkManager::netlinkcache::~netlinkcache()
218 void NetLinkManager::netlinkcache::up() throw (socket_exception)
220 if (_state != SOCKET_DOWN)
221 throw socket_exception(
"socket is already up");
224 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
226 _nl_handle = nl_socket_alloc();
228 _nl_handle = nl_handle_alloc();
232 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
233 ret = nl_cache_mngr_alloc((
struct nl_sock*)_nl_handle, _protocol, NL_AUTO_PROVIDE, &_mngr);
236 throw socket_exception(
"can not allocate netlink cache manager");
238 _mngr = nl_cache_mngr_alloc((
struct nl_handle*)_nl_handle, _protocol, NL_AUTO_PROVIDE);
242 throw socket_exception(
"can not allocate netlink cache manager");
244 for (std::map<std::string, struct nl_cache*>::iterator iter = _caches.begin(); iter != _caches.end(); ++iter)
246 const std::string &cachename = (*iter).first;
247 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
249 ret = nl_cache_mngr_add(_mngr, cachename.c_str(), &nl_cache_callback,
this, &c);
252 throw socket_exception(std::string(
"can not allocate netlink cache ") + cachename);
254 struct nl_cache *c = nl_cache_mngr_add(_mngr, cachename.c_str(), &nl_cache_callback);
258 throw socket_exception(std::string(
"can not allocate netlink cache ") + cachename);
267 void NetLinkManager::netlinkcache::down() throw (socket_exception)
269 if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
270 throw socket_exception(
"socket is not up");
273 nl_cache_mngr_free(_mngr);
275 #if defined HAVE_LIBNL2 || HAVE_LIBNL3
277 nl_socket_free((
struct nl_sock*)_nl_handle);
281 if (_state == SOCKET_UNMANAGED)
282 _state = SOCKET_DESTROYED;
284 _state = SOCKET_DOWN;
287 int NetLinkManager::netlinkcache::fd()
const throw (socket_exception)
289 if (_state == SOCKET_DOWN)
throw socket_exception(
"fd not available");
290 return nl_cache_mngr_get_fd(_mngr);
293 void NetLinkManager::netlinkcache::receive() throw (socket_exception)
295 if (_state == SOCKET_DOWN)
throw socket_exception(
"socket not connected");
296 nl_cache_mngr_data_ready(_mngr);
298 int ret = nl_cache_mngr_data_ready(_mngr);
306 throw socket_exception(
"can not receive data from netlink manager");
310 void NetLinkManager::netlinkcache::add(
const std::string &cachename)
throw (socket_exception)
312 if (_state != SOCKET_DOWN)
313 throw socket_exception(
"socket is already up; adding not possible");
315 std::map<std::string, struct nl_cache*>::const_iterator iter = _caches.find(cachename);
316 if (iter != _caches.end())
throw socket_exception(
"cache already added");
319 _caches[cachename] = NULL;
322 struct nl_cache* NetLinkManager::netlinkcache::get(
const std::string &cachename)
const throw (socket_exception)
324 if (_state == SOCKET_DOWN)
throw socket_exception(
"socket not available");
326 std::map<std::string, struct nl_cache*>::const_iterator iter = _caches.find(cachename);
327 if (iter == _caches.end())
throw socket_exception(
"cache not available");
329 return (*iter).second;
332 NetLinkManager::NetLinkManager()
333 : _route_cache(NETLINK_ROUTE),
_running(true)
336 _route_cache.add(
"route/link");
337 _route_cache.add(
"route/addr");
343 NetLinkManager::~NetLinkManager()
350 }
catch (
const socket_exception&) {
356 void NetLinkManager::up() throw ()
359 _sock.add(&_route_cache);
365 void NetLinkManager::down() throw ()
374 void NetLinkManager::__cancellation() throw ()
380 void NetLinkManager::run() throw ()
386 _sock.select(&socks, NULL, NULL, NULL);
388 for (socketset::iterator iter = socks.begin(); iter != socks.end(); ++iter) {
390 netlinkcache &cache =
dynamic_cast<netlinkcache&
>(**iter);
392 }
catch (
const bad_cast&) { };
395 }
catch (
const socket_exception&) {
401 const std::list<vaddress> NetLinkManager::getAddressList(
const vinterface &iface,
const std::string &scope)
405 std::list<vaddress> addresses;
407 struct rtnl_addr *filter = rtnl_addr_alloc();
408 const std::string i = iface.
toString();
409 int ifindex = rtnl_link_name2i(_route_cache.get(
"route/link"), i.c_str());
411 rtnl_addr_set_ifindex(filter, ifindex);
414 if (scope.length() > 0) {
415 rtnl_addr_set_scope(filter, rtnl_str2scope(scope.c_str()));
419 nl_cache_foreach_filter(_route_cache.get(
"route/addr"), (
struct nl_object *) filter,
add_addr_to_list, &addresses);
422 rtnl_addr_put(filter);
427 const vinterface NetLinkManager::getInterface(
const int ifindex)
const
430 rtnl_link_i2name(_route_cache.get(
"route/link"), ifindex, (
char*)&buf,
sizeof buf);
431 return std::string((
char*)&buf);