Exemple #1
0
/*
 * Given an interface name (e.g., eth0), return the MAC address in human
 * readable format (e.g., 00:11:52:12:D9:A0).  Return NULL for no match.
 */
char *iface_mac2str(char *ifname) {
    int buflen = 20;
    char *buf = NULL;
    struct nl_handle *handle = NULL;
    struct nl_cache *cache = NULL;
    struct rtnl_link *link = NULL;
    struct nl_addr *addr = NULL;

    if (ifname == NULL) {
        return NULL;
    }

    if ((cache = _iface_get_link_cache(&handle)) == NULL) {
        return NULL;
    }

    if ((link = rtnl_link_get_by_name(cache, ifname)) == NULL) {
        goto mac2str_error2;
    }

    if ((addr = rtnl_link_get_addr(link)) == NULL) {
        goto mac2str_error3;
    }

    if ((buf = calloc(sizeof(char *), buflen)) == NULL) {
        goto mac2str_error4;
    }

    if ((buf = nl_addr2str(addr, buf, buflen)) != NULL) {
        buf = str2upper(buf);
    }

mac2str_error4:
    nl_addr_destroy(addr);
mac2str_error3:
    rtnl_link_put(link);
mac2str_error2:
    nl_close(handle);
    nl_handle_destroy(handle);

    return buf;
}
Exemple #2
0
static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
{
	struct nl_cache *link_cache;
	char buf[128];

	link_cache = nl_cache_mngt_require_safe("route/link");

	nl_dump(dp, "nexthop");

	if (nh->ce_mask & NH_ATTR_GATEWAY)
		nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway,
						   buf, sizeof(buf)));

	if(nh->ce_mask & NH_ATTR_IFINDEX) {
		if (link_cache) {
			nl_dump(dp, " dev %s",
				rtnl_link_i2name(link_cache,
						 nh->rtnh_ifindex,
						 buf, sizeof(buf)));
		} else
			nl_dump(dp, " dev %d", nh->rtnh_ifindex);
	}

	if (nh->ce_mask & NH_ATTR_WEIGHT)
		nl_dump(dp, " weight %u", nh->rtnh_weight);

	if (nh->ce_mask & NH_ATTR_REALMS)
		nl_dump(dp, " realm %04x:%04x",
			RTNL_REALM_FROM(nh->rtnh_realms),
			RTNL_REALM_TO(nh->rtnh_realms));

	if (nh->ce_mask & NH_ATTR_FLAGS)
		nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags,
							buf, sizeof(buf)));

	if (link_cache)
		nl_cache_put(link_cache);
}
Exemple #3
0
int netlink_wrapper::get_neigh(const char* ipaddr, netlink_neigh_info* new_neigh_info)
{
	auto_unlocker lock(m_cache_lock);
	nl_logfunc("--->netlink_listener::get_neigh");
	nl_object* obj;
	rtnl_neigh* neigh;
	char addr_str[256];

	BULLSEYE_EXCLUDE_BLOCK_START
	if (!new_neigh_info) {
		nl_logerr("Illegal argument. user pass NULL neigh_info to fill");
		return -1;
	}
	BULLSEYE_EXCLUDE_BLOCK_END

	obj = nl_cache_get_first(m_cache_neigh);
	while (obj) {
		nl_object_get(obj); //Acquire a reference on a cache object. cache won't use/free it until calling to nl_object_put(obj)
		neigh = (rtnl_neigh*) obj;
		nl_addr* addr = rtnl_neigh_get_dst(neigh);
		if (addr) {
			nl_addr2str(addr, addr_str, 255);
			if (!strcmp(addr_str, ipaddr)) {
				new_neigh_info->fill(neigh);
				nl_object_put(obj);
				nl_logdbg("neigh - DST_IP:%s LLADDR:%s", addr_str, new_neigh_info->lladdr_str.c_str() );
				nl_logfunc("<---netlink_listener::get_neigh");
				return 1;
			}
		}
		nl_object_put(obj);
		obj = nl_cache_get_next(obj);
	}

	nl_logfunc("<---netlink_listener::get_neigh");
	return 0;
}
static void nh_dump_env(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
{
	struct nl_cache *link_cache;
	char buf[128];

	link_cache = nl_cache_mngt_require("route/link");

	if (nh->ce_mask & NH_ATTR_GATEWAY)
		nl_dump_line(dp, "ROUTE_NH%d_VIA=%s\n", dp->dp_ivar,
			nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf)));

	if(nh->ce_mask & NH_ATTR_IFINDEX) {
		if (link_cache) {
			nl_dump_line(dp, "ROUTE_NH%d_DEV=%s\n", dp->dp_ivar,
					rtnl_link_i2name(link_cache,
						 nh->rtnh_ifindex,
						 buf, sizeof(buf)));
		} else
			nl_dump_line(dp, "ROUTE_NH%d_DEV=%d\n", dp->dp_ivar,
					nh->rtnh_ifindex);
	}

	if (nh->ce_mask & NH_ATTR_WEIGHT)
		nl_dump_line(dp, "ROUTE_NH%d_WEIGHT=%u\n", dp->dp_ivar,
				nh->rtnh_weight);

	if (nh->ce_mask & NH_ATTR_REALMS)
		nl_dump_line(dp, "ROUTE_NH%d_REALM=%04x:%04x\n", dp->dp_ivar,
			RTNL_REALM_FROM(nh->rtnh_realms),
			RTNL_REALM_TO(nh->rtnh_realms));

	if (nh->ce_mask & NH_ATTR_FLAGS)
		nl_dump_line(dp, "ROUTE_NH%d_FLAGS=<%s>\n", dp->dp_ivar,
			rtnl_route_nh_flags2str(nh->rtnh_flags,
							buf, sizeof(buf)));
}
Exemple #5
0
static int addr_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
{
	struct rtnl_addr *addr = (struct rtnl_addr *) obj;
	struct nl_cache *link_cache;
	char buf[128];
	int line = 0;

	dp_dump_line(p, line++, "<address>\n");
	dp_dump_line(p, line++, "  <family>%s</family>\n",
		     nl_af2str(addr->a_family, buf, sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_LOCAL)
		dp_dump_line(p, line++, "  <local>%s</local>\n",
			     nl_addr2str(addr->a_local, buf, sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_PEER)
		dp_dump_line(p, line++, "  <peer>%s</peer>\n",
			     nl_addr2str(addr->a_peer, buf, sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_BROADCAST)
		dp_dump_line(p, line++, "  <broadcast>%s</broadcast>\n",
			     nl_addr2str(addr->a_bcast, buf, sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_ANYCAST)
		dp_dump_line(p, line++, "  <anycast>%s</anycast>\n",
			     nl_addr2str(addr->a_anycast, buf, sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_MULTICAST)
		dp_dump_line(p, line++, "  <multicast>%s</multicast>\n",
			     nl_addr2str(addr->a_multicast, buf,
					   sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_PREFIXLEN)
		dp_dump_line(p, line++, "  <prefixlen>%u</prefixlen>\n",
			     addr->a_prefixlen);
	link_cache = nl_cache_mngt_require("route/link");

	if (link_cache)
		dp_dump_line(p, line++, "  <device>%s</device>\n",
			     rtnl_link_i2name(link_cache, addr->a_ifindex,
			     		      buf, sizeof(buf)));
	else
		dp_dump_line(p, line++, "  <device>%u</device>\n",
			     addr->a_ifindex);

	if (addr->a_mask & ADDR_ATTR_SCOPE)
		dp_dump_line(p, line++, "  <scope>%s</scope>\n",
			     rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));

	if (addr->a_mask & ADDR_ATTR_LABEL)
		dp_dump_line(p, line++, "  <label>%s</label>\n", addr->a_label);

	rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
	if (buf[0])
		dp_dump_line(p, line++, "  <flags>%s</flags>\n", buf);

	if (addr->a_mask & ADDR_ATTR_CACHEINFO) {
		struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;

		dp_dump_line(p, line++, "  <cacheinfo>\n");

		dp_dump_line(p, line++, "    <valid>%s</valid>\n",
			     ci->aci_valid == 0xFFFFFFFFU ? "forever" :
			     nl_msec2str(ci->aci_valid * 1000,
					   buf, sizeof(buf)));

		dp_dump_line(p, line++, "    <prefered>%s</prefered>\n",
			     ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
			     nl_msec2str(ci->aci_prefered * 1000,
					 buf, sizeof(buf)));

		dp_dump_line(p, line++, "    <created>%s</created>\n",
			     nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
					 buf, sizeof(buf)));

		dp_dump_line(p, line++, "    <last-update>%s</last-update>\n",
			     nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
					 buf, sizeof(buf)));

		dp_dump_line(p, line++, "  </cacheinfo>\n");
	}

	dp_dump_line(p, line++, "</address>\n");

	return line;
}
Exemple #6
0
static void nl_ihandler_cb(struct incident *i, void *ctx)
{
	g_debug("%s i %p ctx %p", __PRETTY_FUNCTION__, i, ctx);
	struct connection *con;
	incident_value_con_get(i, "con", &con);

	char *remote = con->remote.ip_string;
	char *local = con->local.ip_string;
	char *prefix = "::ffff:";
	if( strncmp(local, prefix, strlen(prefix)) == 0)
		local += strlen(prefix);
	if( strncmp(remote, prefix, strlen(prefix)) == 0)
		remote += strlen(prefix);


	int ifindex;
	int err;
	{
		g_debug("local addr %s remote addr %s", local, remote);
		struct rtnl_addr *addr = rtnl_addr_alloc();
	
		struct nl_addr *a;

		if ( ( err = nl_addr_parse(local, AF_UNSPEC, &a)) != 0 )
			g_critical("could not parse addr %s (%s)", local, nl_geterror(err));
		rtnl_addr_set_local(addr, a);
		nl_addr_put(a);
	
		struct rtnl_addr *res = NULL;
		nl_cache_foreach_filter(nl_runtime.addr_cache, OBJ_CAST(addr), cache_lookup_cb, &res);
	
		g_critical("LOCAL RTNL_ADDR %p", res);
	
	/*	struct nl_dump_params params = {
			.dp_type = NL_DUMP_LINE,
			.dp_fd = stdout,
		};
		nl_cache_dump_filter(nl_runtime.addr_cache, &params, OBJ_CAST(addr));
	*/
		ifindex = rtnl_addr_get_ifindex(res);
	}
	

	struct rtnl_neigh *res = NULL;
	{
		struct rtnl_neigh *neigh = rtnl_neigh_alloc();
		rtnl_neigh_set_ifindex(neigh, ifindex);
		struct nl_addr *a;
		if ( ( err = nl_addr_parse(remote, AF_UNSPEC, &a)) != 0 )
			g_critical("could not parse addr %s (%s)", remote, nl_geterror(err));
		rtnl_neigh_set_dst(neigh, a);
		nl_addr_put(a);

		nl_cache_foreach_filter(nl_runtime.neigh_cache, OBJ_CAST(neigh), cache_lookup_cb, &res);
	}

	if( res )
	{
		g_critical("GOT NEIGH %p", res);
		struct nl_addr *lladdr = rtnl_neigh_get_lladdr(res);
		char buf[123];
		nl_addr2str(lladdr, buf, sizeof(buf));
		g_critical("GOT NEIGH %s", buf);

		struct incident *i = incident_new("dionaea.module.nl.connection.info.mac");
		incident_value_string_set(i, "mac", g_string_new(buf));
		incident_value_con_set(i, "con", con);
		incident_report(i);
		incident_free(i);
	}
}
Exemple #7
0
static void nl_obj_input(struct nl_object *obj, void *arg)
{
	struct _obj
	{
		NLHDR_COMMON
	};

	struct _obj *o = (struct _obj *)obj;

	if( o->ce_msgtype == RTM_NEWLINK  || o->ce_msgtype == RTM_DELLINK ) 
	{
		struct rtnl_link *link = (struct rtnl_link *)obj;
		struct nl_addr *a = rtnl_link_get_addr(link);
		char buf[123];
		nl_addr2str(a, buf, sizeof(buf));
		int ifindex = rtnl_link_get_ifindex(link);
		bool active = rtnl_link_get_flags(link) & IFF_UP;
		char *iface = rtnl_link_get_name(link);
		if( o->ce_msgtype == RTM_NEWLINK ) 
		{
			struct link_addr *nla = g_hash_table_lookup(nl_runtime.link_addr_cache, &ifindex);
			if( nla == NULL )
			{
				g_critical("LINK NEW %s %i", iface, ifindex);
				struct link_addr *nla = link_addr_new(iface, ifindex, active);
				g_hash_table_insert(nl_runtime.link_addr_cache, &nla->ifindex, nla);
			}else
			{
				g_critical("LINK CHANGE %s %i", iface, ifindex);
				GHashTableIter iter;
				gpointer key, value;
				g_hash_table_iter_init(&iter, nla->addrs);
				if( active != nla->active )
				{
					while( g_hash_table_iter_next(&iter, &key, &value) )
					{
						struct incident *i;
						if( active )
						{
							g_critical("LINK UP");
							i = incident_new("dionaea.module.nl.addr.new");
						}else
						{
							g_critical("LINK DOWN");
							i = incident_new("dionaea.module.nl.addr.del");
						}
						incident_value_string_set(i, "addr", g_string_new(key));
						incident_value_string_set(i, "iface", g_string_new(nla->iface));
						incident_value_int_set(i, "scope", nla->ifindex);
						incident_report(i);
						incident_free(i);
					}
					nla->active = active;
				}
			}
		}else
		if( o->ce_msgtype == RTM_DELLINK ) 
		{
			g_critical("LINK DEL %s %i", iface, ifindex);
			struct link_addr *nla = g_hash_table_lookup(nl_runtime.link_addr_cache, &ifindex);
			g_hash_table_remove(nl_runtime.link_addr_cache, &ifindex);
			link_addr_free(nla);
		}
	}else
	if( o->ce_msgtype == RTM_NEWADDR  || o->ce_msgtype == RTM_DELADDR ) 
	{
		char buf[128];
		struct rtnl_addr *addr = (struct rtnl_addr *)obj;
		struct nl_addr *a = rtnl_addr_get_local(addr);
		int ifindex = rtnl_addr_get_ifindex(addr);
		nl_addr2str(a, buf, 128);
		char *slash; 
		if( (slash = strstr(buf, "/")) != NULL)
			*slash = '\0';
		char *saddr = NULL;

		struct link_addr *nla = g_hash_table_lookup(nl_runtime.link_addr_cache, &ifindex);
		if( !nla )
			return;

		if( o->ce_msgtype == RTM_NEWADDR ) 
		{
			if( g_hash_table_lookup(nla->addrs, buf) == NULL )
			{
				g_warning("NEW ADDR %s!", buf);
				saddr = g_strdup(buf);
				g_hash_table_insert(nla->addrs, saddr, saddr);

				if( nla->active )
				{
					struct incident *i = incident_new("dionaea.module.nl.addr.new");
					incident_value_string_set(i, "addr", g_string_new(saddr));
					incident_value_string_set(i, "iface", g_string_new(nla->iface));
					incident_value_int_set(i, "scope", nla->ifindex);
					incident_report(i);
					incident_free(i);
				}
			}
		}else
		if( o->ce_msgtype == RTM_DELADDR )
		{
			if( ( saddr = g_hash_table_lookup(nla->addrs, buf) ) != NULL )
			{
				g_warning("DEL ADDR! %s", buf);
				if( nla->active )
				{
					struct incident *i = incident_new("dionaea.module.nl.addr.del");
					incident_value_string_set(i, "addr", g_string_new(saddr));
					incident_value_string_set(i, "iface", g_string_new(nla->iface));
					incident_value_int_set(i, "scope", nla->ifindex);
					incident_report(i);
					incident_free(i);
				}
				g_hash_table_remove(nla->addrs, buf);
				g_free(saddr);
			}
		}
	}
/*
	struct nl_dump_params dp = {
		.dp_type = NL_DUMP_STATS,
		.dp_fd = stdout,
		.dp_dump_msgtype = 1,
	};

	nl_object_dump(obj, &dp);

	struct nl_dump_params params = {
		.dp_type = NL_DUMP_LINE,
		.dp_fd = stdout,
		.dp_prefix = 1,
	};
	g_debug("addr cache");
	nl_cache_dump(nl_runtime.addr_cache, &params);
	g_debug("arp cache");
	nl_cache_dump(nl_runtime.neigh_cache, &params);
	g_debug("link cache");
	nl_cache_dump(nl_runtime.link_cache, &params);
*/
}
static void route_proc_cb(struct nl_object *c, void *arg)
{
        struct ip_lookup_res *res = (struct ip_lookup_res*) arg;
	struct rtnl_route *route = (struct rtnl_route *) c;
	struct nl_cache *link_cache;
        struct nl_addr *addr;
        struct rtnl_nexthop *nh;
        int prefix_len;
        int oif;
	char buf[64];

	link_cache = nl_cache_mngt_require("route/link");

        addr = rtnl_route_get_dst(route);
        if (addr) {
		printf("%s", nl_addr2str(addr, buf, sizeof(buf)));
                res->dstaddr = *(uint32_t *) nl_addr_get_binary_addr(addr);
        }

        prefix_len = rtnl_route_get_dst_len(route);
        if (prefix_len)
                printf("/%d ", prefix_len);
        else
                printf("default ");

        addr = rtnl_route_get_src(route);
        if (addr) 
		printf("src %s ", nl_addr2str(addr, buf, sizeof(buf)));

        addr = rtnl_route_get_pref_src(route);
        if (addr)
		printf("preferred src %s ", nl_addr2str(addr, buf, sizeof(buf)));

        addr = rtnl_route_get_gateway(route);
        if (addr) { 
		printf("via %s ", nl_addr2str(addr, buf, sizeof(buf)));
                res->nh_addr = *(uint32_t*) nl_addr_get_binary_addr(addr);
        }
        else {
                res->nh_addr = 0;
        }

        oif = rtnl_route_get_oif(route);
        res->oif = oif;
        if (oif != RTNL_LINK_NOT_FOUND && link_cache) {
	        printf("dev %s ", rtnl_link_i2name(link_cache, oif,
						 buf, sizeof(buf)));
                rtnl_link_i2name(link_cache, oif, res->oifname, sizeof(res->oifname));
        }
        
        /* Declaration of rtnl_route_nh_get_gateway() is missing from 
         * include/netlink/route/nexthop.h, there is no way to inspect
         * each nexthop for gateway information, will just use gateway 
         * info stored in rtnl_route struct. The probem is only present
         * libnl 1 */
        /*
        nl_list_for_each_entry(nh, rtnl_route_get_nexthops(route), rtnh_list) {

        }
        */
                
        printf("\n");

}
void NetlinkManager::netlinkRouteUpdated(
    struct nl_cache* /*cache*/,
    struct nl_object* obj,
    int nlOperation,
    void* data) {
  NetlinkManager* nlm = static_cast<NetlinkManager*>(data);
  std::string operation = nlm->nlOperationToStr(nlOperation);
  if (operation == "unknown") {
    VLOG(1) << "Ignoring an unknown route update";
    return;
  }

  VLOG(2) << "Received a " << operation << " netlink route update message";
  struct rtnl_route* route = (struct rtnl_route*)obj;

  if (rtnl_route_get_type(route) != RTN_UNICAST) {
    VLOG(1) << "Ignoring non-unicast route update";
    return;
  }

  struct nl_addr* nlDst = rtnl_route_get_dst(route);
  const uint8_t ipLen = nl_addr_get_prefixlen(nlDst);
  char strDst[ipLen];
  nl_addr2str(nlDst, strDst, ipLen);

  int numNexthops = rtnl_route_get_nnexthops(route);
  if (!numNexthops) {
    VLOG(0) << "Could not find next hop for route update for " << strDst;
    struct nl_dump_params dumpParams = initDumpParams();
    nl_object_dump((nl_object*)route, &dumpParams);
    return;
  }

  std::vector<BinaryAddress> nexthops;
  {
    std::lock_guard<std::mutex> lock(nlm->interfacesMutex_);
    nexthops = getNextHops(route, ipLen, nlm->monitoredInterfaces_);
  }

  if (nexthops.empty()) {
    VLOG(1) << operation << " Route update for " << strDst
            << " has no valid nexthop";
    return;
  }

  if (FLAGS_debug) {
    VLOG(1) << "Got " << operation << " route update for " << strDst;
    return;
  }

  switch (nlOperation) {
    case NL_ACT_NEW: {
      nlm->addRouteViaFbossThrift(nlDst, nexthops);
      break;
    }
    case NL_ACT_DEL: {
      nlm->deleteRouteViaFbossThrift(nlDst);
      break;
    }
    case NL_ACT_CHANGE: {
      VLOG(2) << "Not updating state due to unimplemented"
              << "NL_ACT_CHANGE netlink operation";
      break;
    }
    default: {
      VLOG(0) << "Not updating state due to unknown netlink operation "
              << std::to_string(nlOperation);
      break; /* NL_ACT_??? */
    }
  }
  return;
}
static int addr_dump_env(struct nl_object *obj, struct nl_dump_params *p)
{
	struct rtnl_addr *addr = (struct rtnl_addr *) obj;
	struct nl_cache *link_cache;
	char buf[128];
	int line = 0;

	dp_dump_line(p, line++, "ADDR_FAMILY=%s\n",
		     nl_af2str(addr->a_family, buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_LOCAL)
		dp_dump_line(p, line++, "ADDR_LOCAL=%s\n",
			     nl_addr2str(addr->a_local, buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_PEER)
		dp_dump_line(p, line++, "ADDR_PEER=%s\n",
			     nl_addr2str(addr->a_peer, buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_BROADCAST)
		dp_dump_line(p, line++, "ADDR_BROADCAST=%s\n",
			     nl_addr2str(addr->a_bcast, buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_ANYCAST)
		dp_dump_line(p, line++, "ADDR_ANYCAST=%s\n",
			     nl_addr2str(addr->a_anycast, buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_MULTICAST)
		dp_dump_line(p, line++, "ADDR_MULTICAST=%s\n",
			     nl_addr2str(addr->a_multicast, buf,
					   sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_PREFIXLEN)
		dp_dump_line(p, line++, "ADDR_PREFIXLEN=%u\n",
			     addr->a_prefixlen);
	link_cache = nl_cache_mngt_require("route/link");

	dp_dump_line(p, line++, "ADDR_IFINDEX=%u\n", addr->a_ifindex);
	if (link_cache)
		dp_dump_line(p, line++, "ADDR_IFNAME=%s\n",
			     rtnl_link_i2name(link_cache, addr->a_ifindex,
			     		      buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_SCOPE)
		dp_dump_line(p, line++, "ADDR_SCOPE=%s\n",
			     rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));

	if (addr->ce_mask & ADDR_ATTR_LABEL)
		dp_dump_line(p, line++, "ADDR_LABEL=%s\n", addr->a_label);

	rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
	if (buf[0])
		dp_dump_line(p, line++, "ADDR_FLAGS=%s\n", buf);

	if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
		struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;

		dp_dump_line(p, line++, "ADDR_CACHEINFO_VALID=%s\n",
			     ci->aci_valid == 0xFFFFFFFFU ? "forever" :
			     nl_msec2str(ci->aci_valid * 1000,
					   buf, sizeof(buf)));

		dp_dump_line(p, line++, "ADDR_CACHEINFO_PREFERED=%s\n",
			     ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
			     nl_msec2str(ci->aci_prefered * 1000,
					 buf, sizeof(buf)));

		dp_dump_line(p, line++, "ADDR_CACHEINFO_CREATED=%s\n",
			     nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
					 buf, sizeof(buf)));

		dp_dump_line(p, line++, "ADDR_CACHEINFO_LASTUPDATE=%s\n",
			     nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
					 buf, sizeof(buf)));
	}

	return line;
}
Exemple #11
0
static void inet6_dump_details(struct rtnl_link *link,
				struct nl_dump_params *p, void *data)
{
	struct inet6_data *i6 = data;
	struct nl_addr *addr;
	char buf[64], buf2[64];
	int i, n = 0;

	nl_dump_line(p, "    ipv6 max-reasm-len %s",
		nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf)));

	nl_dump(p, " <%s>\n",
		inet6_flags2str(i6->i6_flags, buf, sizeof(buf)));


	nl_dump_line(p, "      create-stamp %.2fs reachable-time %s",
		(double) i6->i6_cacheinfo.tstamp / 100.,
		nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf)));

	nl_dump(p, " retrans-time %s\n",
		nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf)));

	addr = nl_addr_build(AF_INET6, &i6->i6_token, sizeof(i6->i6_token));
	nl_dump(p, "      token %s\n",
		nl_addr2str(addr, buf, sizeof(buf)));
	nl_addr_put(addr);

	nl_dump(p, "      link-local address mode %s\n",
		rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode,
						buf, sizeof(buf)));

	nl_dump_line(p, "      devconf:\n");
	nl_dump_line(p, "      ");

	for (i = 0; i < DEVCONF_MAX; i++) {
		uint32_t value = i6->i6_conf[i];
		int x, offset;

		switch (i) {
		case DEVCONF_TEMP_VALID_LFT:
		case DEVCONF_TEMP_PREFERED_LFT:
			nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2));
			break;

		case DEVCONF_RTR_PROBE_INTERVAL:
		case DEVCONF_RTR_SOLICIT_INTERVAL:
		case DEVCONF_RTR_SOLICIT_DELAY:
			nl_msec2str(value, buf2, sizeof(buf2));
			break;

		default:
			snprintf(buf2, sizeof(buf2), "%u", value);
			break;
			
		}

		inet6_devconf2str(i, buf, sizeof(buf));

		offset = 23 - strlen(buf2);
		if (offset < 0)
			offset = 0;

		for (x = strlen(buf); x < offset; x++)
			buf[x] = ' ';

		strncpy(&buf[offset], buf2, strlen(buf2));

		nl_dump_line(p, "%s", buf);

		if (++n == 3) {
			nl_dump(p, "\n");
			nl_dump_line(p, "      ");
			n = 0;
		} else
			nl_dump(p, "  ");
	}

	if (n != 0)
		nl_dump(p, "\n");
}
Exemple #12
0
static void handle_class(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "class", rdata)))
		return;

	ndata.parent = e;

	if (!strcmp(rtnl_tc_get_kind(tc), "htb"))
		element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc));

	find_classes(rtnl_tc_get_handle(tc), &ndata);
	find_qdiscs(rtnl_tc_get_handle(tc), &ndata);
}

static void find_qdiscs(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_qdisc *filter;

	if (!(filter = rtnl_qdisc_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter),
				handle_qdisc, rdata);

	rtnl_qdisc_put(filter);
}

static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata)
{
	struct nl_cache *cls_cache;

	if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0)
		return;

	nl_cache_foreach(cls_cache, handle_cls, rdata);

	nl_cache_free(cls_cache);
}

static void find_classes(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_class *filter;

	if (!(filter = rtnl_class_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(class_cache, OBJ_CAST(filter),
				handle_class, rdata);

	rtnl_class_put(filter);
}

static void handle_qdisc(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "qdisc", rdata)))
		return;

	ndata.parent = e;

	find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata);

	if (rtnl_tc_get_parent(tc) == TC_H_ROOT) {
		find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata);
		find_classes(TC_H_ROOT, &ndata);
	}

	find_classes(rtnl_tc_get_handle(tc), &ndata);
}

static void handle_tc(struct element *e, struct rtnl_link *link)
{
	struct rtnl_qdisc *qdisc;
	int ifindex = rtnl_link_get_ifindex(link);
	struct rdata rdata = {
		.level = 1,
		.parent = e,
	};

	if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0)
		return;

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	nl_cache_free(class_cache);
}

static void update_link_infos(struct element *e, struct rtnl_link *link)
{
	char buf[64];

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link));
	element_update_info(e, "MTU", buf);

	rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf));
	element_update_info(e, "Flags", buf);

	rtnl_link_operstate2str(rtnl_link_get_operstate(link),
				buf, sizeof(buf));
	element_update_info(e, "Operstate", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link));
	element_update_info(e, "IfIndex", buf);

	nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf));
	element_update_info(e, "Address", buf);

	nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf));
	element_update_info(e, "Broadcast", buf);

	rtnl_link_mode2str(rtnl_link_get_linkmode(link),
			   buf, sizeof(buf));
	element_update_info(e, "Mode", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link));
	element_update_info(e, "TXQlen", buf);

	nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf));
	element_update_info(e, "Family", buf);

	element_update_info(e, "Alias",
		rtnl_link_get_ifalias(link) ? : "");

	element_update_info(e, "Qdisc",
		rtnl_link_get_qdisc(link) ? : "");

	if (rtnl_link_get_link(link)) {
		snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link));
		element_update_info(e, "SlaveOfIndex", buf);
	}
}

static void do_link(struct nl_object *obj, void *arg)
{
	struct rtnl_link *link = (struct rtnl_link *) obj;
	struct element *e, *e_parent = NULL;
	int i, master_ifindex;

	if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) {
		/* FIXME: delete element */
		return;
	}

	/* Check if the interface is a slave of another interface */
	if ((master_ifindex = rtnl_link_get_link(link))) {
		char parent[IFNAMSIZ+1];

		rtnl_link_i2name(link_cache, master_ifindex,
				 parent, sizeof(parent));

		e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0);
	}

	if (!(e = element_lookup(grp, rtnl_link_get_name(link),
				 rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT)))
		return;

	if (e->e_flags & ELEMENT_FLAG_CREATED) {
		if (e->e_parent)
			e->e_level = e->e_parent->e_level + 1;

		if (element_set_key_attr(e, "bytes", "packets") ||
		    element_set_usage_attr(e, "bytes"))
			BUG();

		/* FIXME: Update link infos every 1s or so */
		update_link_infos(e, link);

		e->e_flags &= ~ELEMENT_FLAG_CREATED;
	}

	for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
		struct attr_map *m = &link_attrs[i];
		uint64_t c_rx = 0, c_tx = 0;
		int flags = 0;

		if (m->rxid >= 0) {
			c_rx = rtnl_link_get_stat(link, m->rxid);
			flags |= UPDATE_FLAG_RX;
		}

		if (m->txid >= 0) {
			c_tx = rtnl_link_get_stat(link, m->txid);
			flags |= UPDATE_FLAG_TX;
		}

		attr_update(e, m->attrid, c_rx, c_tx, flags);
	}

	if (!c_notc)
		handle_tc(e, link);

	element_notify_update(e, NULL);
	element_lifesign(e, 1);
}

static void netlink_read(void)
{
	int err;

	if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err));
		goto disable;
	}

	if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err));
		goto disable;
	}

	nl_cache_foreach(link_cache, do_link, NULL);

	return;

disable:
	netlink_ops.m_flags &= ~BMON_MODULE_ENABLED;
}

static void netlink_shutdown(void)
{
	nl_cache_free(link_cache);
	nl_cache_free(qdisc_cache);
	nl_socket_free(sock);
}
Exemple #13
0
static void env_dump(struct nl_object *obj, void *arg)
{
	struct nl_dump_params *p = arg;
	struct rtnl_addr *addr = (struct rtnl_addr *) obj;
	struct nl_cache *link_cache;
	struct nl_addr *a;
	static int index = 0;
	char buf[128], pfx[32], *s;

	snprintf(pfx, sizeof(pfx), "ADDR%d", index++);

	nl_dump_line(p, "%s_FAMILY=%s\n", pfx,
		     nl_af2str(rtnl_addr_get_family(addr), buf, sizeof(buf)));

	nl_dump_line(p, "%s_LOCAL=%s\n", pfx,
		     nl_addr2str(rtnl_addr_get_local(addr), buf, sizeof(buf)));

	nl_dump_line(p, "%s_IFINDEX=%u\n", pfx, rtnl_addr_get_ifindex(addr));
	link_cache = nl_cache_mngt_require_safe("route/link");
	if (link_cache)
		nl_dump_line(p, "%s_IFNAME=%s\n", pfx,
			     rtnl_link_i2name(link_cache,
			     		      rtnl_addr_get_ifindex(addr),
			     		      buf, sizeof(buf)));

	if ((a = rtnl_addr_get_peer(addr)))
		nl_dump_line(p, "%s_PEER=%s\n", pfx,
			     nl_addr2str(a, buf, sizeof(buf)));

	if ((a = rtnl_addr_get_broadcast(addr)))
		nl_dump_line(p, "%s_BROADCAST=%s\n", pfx,
			     nl_addr2str(a, buf, sizeof(buf)));

	nl_dump_line(p, "%s_SCOPE=%s\n", pfx,
		     rtnl_scope2str(rtnl_addr_get_scope(addr),
				    buf, sizeof(buf)));

	if ((s = rtnl_addr_get_label(addr)))
		nl_dump_line(p, "%s_LABEL=%s\n", pfx, s);

	rtnl_addr_flags2str(rtnl_addr_get_flags(addr), buf, sizeof(buf));
	if (buf[0])
		nl_dump_line(p, "%s_FLAGS=%s\n", pfx, buf);

	nl_dump_line(p, "%s_CACHEINFO_VALID=%u\n", pfx,
		     rtnl_addr_get_valid_lifetime(addr));

	if (link_cache)
		nl_cache_put(link_cache);

#if 0
	if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
		struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;

		nl_dump_line(p, "ADDR_CACHEINFO_PREFERRED=%u\n",
			     ci->aci_prefered);

		nl_dump_line(p, "ADDR_CACHEINFO_CREATED=%u\n", ci->aci_cstamp);
		nl_dump_line(p, "ADDR_CACHEINFO_LASTUPDATE=%u\n",
			     ci->aci_tstamp);
	}
#endif
}
Exemple #14
0
static void xfrm_ae_dump_line(struct nl_object *a, struct nl_dump_params *p)
{
	char                dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5];
	struct xfrmnl_ae*   ae  =   (struct xfrmnl_ae *) a;
	char                flags[128], buf[128];
	time_t              add_time, use_time;
	struct tm           *add_time_tm, *use_time_tm;

	nl_dump_line(p, "src %s dst %s \n", nl_addr2str(ae->saddr, src, sizeof(src)),
				nl_addr2str(ae->sa_id.daddr, dst, sizeof(dst)));

	nl_dump_line(p, "\tproto %s spi 0x%x reqid %u ",
				nl_ip_proto2str (ae->sa_id.proto, buf, sizeof (buf)),
				ae->sa_id.spi, ae->reqid);

	xfrmnl_ae_flags2str(ae->flags, flags, sizeof (flags));
	nl_dump_line(p, "flags %s(0x%x) mark mask/value 0x%x/0x%x \n", flags,
				ae->flags, ae->mark.m, ae->mark.v);

	nl_dump_line(p, "\tlifetime current: \n");
	nl_dump_line(p, "\t\tbytes %llu packets %llu \n", ae->lifetime_cur.bytes,
				ae->lifetime_cur.packets);
	if (ae->lifetime_cur.add_time != 0)
	{
		add_time = ae->lifetime_cur.add_time;
		add_time_tm = gmtime (&add_time);
		strftime (flags, 128, "%Y-%m-%d %H-%M-%S", add_time_tm);
	}
	else
	{
		sprintf (flags, "%s", "-");
	}

	if (ae->lifetime_cur.use_time != 0)
	{
		use_time = ae->lifetime_cur.use_time;
		use_time_tm = gmtime (&use_time);
		strftime (buf, 128, "%Y-%m-%d %H-%M-%S", use_time_tm);
	}
	else
	{
		sprintf (buf, "%s", "-");
	}
	nl_dump_line(p, "\t\tadd_time: %s, use_time: %s\n", flags, buf);

	nl_dump_line(p, "\treplay info: \n");
	nl_dump_line(p, "\t\tmax age %u max diff %u \n", ae->replay_maxage, ae->replay_maxdiff);

	nl_dump_line(p, "\treplay state info: \n");
	if (ae->replay_state_esn)
	{
		nl_dump_line(p, "\t\toseq %u seq %u oseq_hi %u seq_hi %u replay window: %u \n",
					ae->replay_state_esn->oseq, ae->replay_state_esn->seq,
					ae->replay_state_esn->oseq_hi, ae->replay_state_esn->seq_hi,
					ae->replay_state_esn->replay_window);
	}
	else
	{
		nl_dump_line(p, "\t\toseq %u seq %u bitmap: %u \n", ae->replay_state.oseq,
					ae->replay_state.seq, ae->replay_state.bitmap);
	}

	nl_dump(p, "\n");
}