<commit_before>/*
 * clinkcache.cc
 *
 *  Created on: 25.06.2013
 *      Author: andreas
 */

#include "cnetlink.hpp"

using namespace rofcore;

cnetlink* cnetlink::netlink = (cnetlink*)0;



cnetlink::cnetlink() :
		mngr(0)
{
	try {
		init_caches();
	} catch (...) {}
}



cnetlink::cnetlink(cnetlink const& linkcache) :
		mngr(0)
{
	init_caches();
}



cnetlink::~cnetlink()
{
	destroy_caches();
}



void
cnetlink::init_caches()
{
	int rc = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
	if (rc < 0) {
		rofcore::logging::debug << "clinkcache::clinkcache() failed to allocate netlink cache manager" << std::endl;
		throw eNetLinkCritical("cnetlink::init_caches()");
	}

	rc = nl_cache_mngr_add(mngr, "route/link", (change_func_t)&route_link_cb, NULL, &caches[NL_LINK_CACHE]);

	rc = nl_cache_mngr_add(mngr, "route/addr", (change_func_t)&route_addr_cb, NULL, &caches[NL_ADDR_CACHE]);

	rc = nl_cache_mngr_add(mngr, "route/route", (change_func_t)&route_route_cb, NULL, &caches[NL_ROUTE_CACHE]);

	rc = nl_cache_mngr_add(mngr, "route/neigh", (change_func_t)&route_neigh_cb, NULL, &caches[NL_NEIGH_CACHE]);

	struct nl_object* obj = nl_cache_get_first(caches[NL_LINK_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		rtlinks.add_link(crtlink((struct rtnl_link*)obj));
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	obj = nl_cache_get_first(caches[NL_ADDR_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		unsigned int ifindex = rtnl_addr_get_ifindex((struct rtnl_addr*)obj);
		switch (rtnl_addr_get_family((struct rtnl_addr*)obj)) {
		case AF_INET:
			rtlinks.set_link(ifindex).set_addrs_in4().add_addr(crtaddr_in4((struct rtnl_addr*)obj));
			break;
		case AF_INET6:
			rtlinks.set_link(ifindex).set_addrs_in6().add_addr(crtaddr_in6((struct rtnl_addr*)obj));
			break;
		}
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	obj = nl_cache_get_first(caches[NL_ROUTE_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		int table_id = rtnl_route_get_table((struct rtnl_route*)obj);
		switch (rtnl_route_get_family((struct rtnl_route*)obj)) {
		case AF_INET:
			rtroutes_in4[table_id].add_route(crtroute_in4((struct rtnl_route*)obj));
			break;
		case AF_INET6:
			rtroutes_in6[table_id].add_route(crtroute_in6((struct rtnl_route*)obj));
			break;
		}
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	obj = nl_cache_get_first(caches[NL_NEIGH_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		// not handled at all? was #if 0
#if 0
		switch (rtnl_neigh_get_family((struct rtnl_neigh*)obj)) {
		case AF_INET:	set_neigh_in4(crtneigh_in4((struct rtnl_neigh*)obj)); break;
		case AF_INET6:	set_neigh_in6(crtneigh_in6((struct rtnl_neigh*)obj)); break;
		}
#endif
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	register_filedesc_r(nl_cache_mngr_get_fd(mngr));
}



void
cnetlink::destroy_caches()
{
	deregister_filedesc_r(nl_cache_mngr_get_fd(mngr));

	nl_cache_mngr_free(mngr);
}





cnetlink&
cnetlink::get_instance()
{
	if (0 == cnetlink::netlink) {
		cnetlink::netlink = new cnetlink();
	}
	return *(cnetlink::netlink);
}



void
cnetlink::handle_revent(int fd)
{
	if (fd == nl_cache_mngr_get_fd(mngr)) {
		nl_cache_mngr_data_ready(mngr);
	}
}



/* static C-callback */
void
cnetlink::route_link_cb(struct nl_cache* cache, struct nl_object* obj, int action, void* data)
{
	try {
		if (std::string(nl_object_get_type(obj)) != std::string("route/link")) {
			rofcore::logging::debug << "cnetlink::route_link_cb() ignoring non link object received" << std::endl;
			return;
		}

		unsigned int ifindex = rtnl_link_get_ifindex((struct rtnl_link*)obj);

		nl_object_get(obj); // get reference to object

		crtlink rtlink((struct rtnl_link*)obj);

		switch (action) {
		case NL_ACT_NEW: {
			cnetlink::get_instance().set_links().add_link(rtlink);
			rofcore::logging::debug << rofcore::cnetlink::get_instance().get_links().get_link(ifindex).str() << std::endl;
			cnetlink::get_instance().notify_link_created(ifindex);
		} break;
		case NL_ACT_CHANGE: {
			cnetlink::get_instance().set_links().set_link(rtlink);
			rofcore::logging::debug << rofcore::cnetlink::get_instance().get_links().get_link(ifindex).str() << std::endl;
			cnetlink::get_instance().notify_link_updated(ifindex);
		} break;
		case NL_ACT_DEL: {
			//notify_link_deleted(ifindex);
			cnetlink::get_instance().set_links().drop_link(ifindex);
			rofcore::logging::debug << rofcore::cnetlink::get_instance().get_links().get_link(ifindex).str() << std::endl;
			cnetlink::get_instance().notify_link_deleted(ifindex);
		} break;
		default: {
			rofcore::logging::debug << "route/link: unknown NL action" << std::endl;
		}
		}

		nl_object_put(obj); // release reference to object

	} catch (eNetLinkNotFound& e) {
		// NL_ACT_CHANGE => ifindex not found
	}
}


/* static C-callback */
void
cnetlink::route_addr_cb(struct nl_cache* cache, struct nl_object* obj, int action, void* data)
{
	if (std::string(nl_object_get_type(obj)) != std::string("route/addr")) {
		rofcore::logging::debug << "cnetlink::route_addr_cb() ignoring non addr object received" << std::endl;
		return;
	}

	nl_object_get(obj); // get reference to object

	unsigned int ifindex = rtnl_addr_get_ifindex((struct rtnl_addr*)obj);
	int family = rtnl_addr_get_family((struct rtnl_addr*)obj);

	try {
		switch (action) {
		case NL_ACT_NEW: {<commit_msg>cnetlink => method route_link_cb() => added catch clause for exception crtlink::eRtLinkNotFound<commit_after>/*
 * clinkcache.cc
 *
 *  Created on: 25.06.2013
 *      Author: andreas
 */

#include "cnetlink.hpp"

using namespace rofcore;

cnetlink* cnetlink::netlink = (cnetlink*)0;



cnetlink::cnetlink() :
		mngr(0)
{
	try {
		init_caches();
	} catch (...) {}
}



cnetlink::cnetlink(cnetlink const& linkcache) :
		mngr(0)
{
	init_caches();
}



cnetlink::~cnetlink()
{
	destroy_caches();
}



void
cnetlink::init_caches()
{
	int rc = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
	if (rc < 0) {
		rofcore::logging::debug << "clinkcache::clinkcache() failed to allocate netlink cache manager" << std::endl;
		throw eNetLinkCritical("cnetlink::init_caches()");
	}

	rc = nl_cache_mngr_add(mngr, "route/link", (change_func_t)&route_link_cb, NULL, &caches[NL_LINK_CACHE]);

	rc = nl_cache_mngr_add(mngr, "route/addr", (change_func_t)&route_addr_cb, NULL, &caches[NL_ADDR_CACHE]);

	rc = nl_cache_mngr_add(mngr, "route/route", (change_func_t)&route_route_cb, NULL, &caches[NL_ROUTE_CACHE]);

	rc = nl_cache_mngr_add(mngr, "route/neigh", (change_func_t)&route_neigh_cb, NULL, &caches[NL_NEIGH_CACHE]);

	struct nl_object* obj = nl_cache_get_first(caches[NL_LINK_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		rtlinks.add_link(crtlink((struct rtnl_link*)obj));
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	obj = nl_cache_get_first(caches[NL_ADDR_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		unsigned int ifindex = rtnl_addr_get_ifindex((struct rtnl_addr*)obj);
		switch (rtnl_addr_get_family((struct rtnl_addr*)obj)) {
		case AF_INET:
			rtlinks.set_link(ifindex).set_addrs_in4().add_addr(crtaddr_in4((struct rtnl_addr*)obj));
			break;
		case AF_INET6:
			rtlinks.set_link(ifindex).set_addrs_in6().add_addr(crtaddr_in6((struct rtnl_addr*)obj));
			break;
		}
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	obj = nl_cache_get_first(caches[NL_ROUTE_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		int table_id = rtnl_route_get_table((struct rtnl_route*)obj);
		switch (rtnl_route_get_family((struct rtnl_route*)obj)) {
		case AF_INET:
			rtroutes_in4[table_id].add_route(crtroute_in4((struct rtnl_route*)obj));
			break;
		case AF_INET6:
			rtroutes_in6[table_id].add_route(crtroute_in6((struct rtnl_route*)obj));
			break;
		}
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	obj = nl_cache_get_first(caches[NL_NEIGH_CACHE]);
	while (0 != obj) {
		nl_object_get(obj);
		// not handled at all? was #if 0
#if 0
		switch (rtnl_neigh_get_family((struct rtnl_neigh*)obj)) {
		case AF_INET:	set_neigh_in4(crtneigh_in4((struct rtnl_neigh*)obj)); break;
		case AF_INET6:	set_neigh_in6(crtneigh_in6((struct rtnl_neigh*)obj)); break;
		}
#endif
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	register_filedesc_r(nl_cache_mngr_get_fd(mngr));
}



void
cnetlink::destroy_caches()
{
	deregister_filedesc_r(nl_cache_mngr_get_fd(mngr));

	nl_cache_mngr_free(mngr);
}





cnetlink&
cnetlink::get_instance()
{
	if (0 == cnetlink::netlink) {
		cnetlink::netlink = new cnetlink();
	}
	return *(cnetlink::netlink);
}



void
cnetlink::handle_revent(int fd)
{
	if (fd == nl_cache_mngr_get_fd(mngr)) {
		nl_cache_mngr_data_ready(mngr);
	}
}



/* static C-callback */
void
cnetlink::route_link_cb(struct nl_cache* cache, struct nl_object* obj, int action, void* data)
{
	try {
		if (std::string(nl_object_get_type(obj)) != std::string("route/link")) {
			rofcore::logging::debug << "cnetlink::route_link_cb() ignoring non link object received" << std::endl;
			return;
		}

		unsigned int ifindex = rtnl_link_get_ifindex((struct rtnl_link*)obj);

		nl_object_get(obj); // get reference to object

		crtlink rtlink((struct rtnl_link*)obj);

		switch (action) {
		case NL_ACT_NEW: {
			cnetlink::get_instance().set_links().add_link(rtlink);
			rofcore::logging::debug << rofcore::cnetlink::get_instance().get_links().get_link(ifindex).str() << std::endl;
			cnetlink::get_instance().notify_link_created(ifindex);
		} break;
		case NL_ACT_CHANGE: {
			cnetlink::get_instance().set_links().set_link(rtlink);
			rofcore::logging::debug << rofcore::cnetlink::get_instance().get_links().get_link(ifindex).str() << std::endl;
			cnetlink::get_instance().notify_link_updated(ifindex);
		} break;
		case NL_ACT_DEL: {
			//notify_link_deleted(ifindex);
			cnetlink::get_instance().set_links().drop_link(ifindex);
			rofcore::logging::debug << rofcore::cnetlink::get_instance().get_links().get_link(ifindex).str() << std::endl;
			cnetlink::get_instance().notify_link_deleted(ifindex);
		} break;
		default: {
			rofcore::logging::debug << "route/link: unknown NL action" << std::endl;
		}
		}

		nl_object_put(obj); // release reference to object

	} catch (eNetLinkNotFound& e) {
		// NL_ACT_CHANGE => ifindex not found
	} catch (crtlink::eRtLinkNotFound& e) {

	}
}


/* static C-callback */
void
cnetlink::route_addr_cb(struct nl_cache* cache, struct nl_object* obj, int action, void* data)
{
	if (std::string(nl_object_get_type(obj)) != std::string("route/addr")) {
		rofcore::logging::debug << "cnetlink::route_addr_cb() ignoring non addr object received" << std::endl;
		return;
	}

	nl_object_get(obj); // get reference to object

	unsigned int ifindex = rtnl_addr_get_ifindex((struct rtnl_addr*)obj);
	int family = rtnl_addr_get_family((struct rtnl_addr*)obj);

	try {
		switch (action) {
		case NL_ACT_NEW: {
{'fraction_non_alphanumeric': 0.15190458579881658, 'fraction_numerical': 0.00628698224852071, 'mean_word_length': 5.854879594423321, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7298624', 'n_tokens_mistral': 4697, 'n_tokens_neox': 4367, 'n_words': 655}