const std::list<vaddress> NetLinkManager::getAddressList(const vinterface &interface, const vaddress::Family f)
	{
		ibrcommon::MutexLock l(_call_mutex);

		if (_refresh_cache)
		{
			nl_cache_free(_addr_cache);
			nl_cache_free(_link_cache);

			_link_cache = rtnl_link_alloc_cache(_handle);

			if (_link_cache == NULL)
			{
				throw ibrcommon::vsocket_exception("netlink cache allocation failed");
			}

			_addr_cache = rtnl_addr_alloc_cache(_handle);

			if (_addr_cache == NULL)
			{
				nl_cache_free(_link_cache);
				throw ibrcommon::vsocket_exception("netlink cache allocation failed");
			}

			// mark the cache as refreshed
			_refresh_cache = false;
		}

		std::list<vaddress> addresses;

		struct rtnl_addr *filter = rtnl_addr_alloc();
		const std::string i = interface.toString();
		rtnl_addr_set_ifindex(filter, rtnl_link_name2i(_link_cache, i.c_str()));

		if (f == vaddress::VADDRESS_UNSPEC)
		{
			rtnl_addr_set_family(filter, AF_INET6);
			nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
									add_addr_to_list, &addresses);

			rtnl_addr_set_family(filter, AF_INET);
			nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
									add_addr_to_list, &addresses);
		}
		else
		{
			rtnl_addr_set_family(filter, f);
			nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
									add_addr_to_list, &addresses);
		}

		rtnl_addr_put(filter);

		return addresses;
	}
Example #2
0
/*
 * Get the first AF_INET address on 'link'. Returns 0 if successful. Caller
 * must release reference to *addr.
 */
static int get_link_inet_addr(struct nl_sock *sk, struct rtnl_link *link,
        struct nl_addr **addr)
{
    struct nl_cache *addr_cache;
    int err;
    err = rtnl_addr_alloc_cache(sk, &addr_cache);
    if (err < 0) {
        warnx("rtnl_addr_alloc_cache() failed: %s", nl_geterror(err));
        return 1;
    }

    /* Retrieve the first AF_INET address on the requested interface. */
    struct rtnl_addr *filter;
    filter = rtnl_addr_alloc();
    assert(filter);
    rtnl_addr_set_ifindex(filter, rtnl_link_get_ifindex(link));
    rtnl_addr_set_family(filter, AF_INET);

    *addr = NULL;
    nl_cache_foreach_filter(addr_cache, (struct nl_object *)filter,
            match_first_addr, addr);
    if (*addr == NULL) {
        warnx("No AF_INET address found on veth");
        
        rtnl_addr_put(filter);
        nl_cache_free(addr_cache);
        return 1;
    }

    rtnl_addr_put(filter);
    nl_cache_free(addr_cache);
    return 0;
}
Example #3
0
static void __delete_link(int ifindex, struct rtnl_cls *filter)
{
	struct nl_cache *cache;
	uint32_t parent = rtnl_tc_get_parent((struct rtnl_tc *) filter);

	cache = nl_cli_cls_alloc_cache(sock, ifindex, parent);
	nl_cache_foreach_filter(cache, OBJ_CAST(filter), delete_cb, NULL);
	nl_cache_free(cache);
}
int main(int argc, char *argv[])
{
	struct rtnl_neigh *neigh;
	struct nl_cache *link_cache, *neigh_cache;
 
	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	neigh_cache = nl_cli_neigh_alloc_cache(sock);
 	neigh = nl_cli_neigh_alloc();
 
	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_FAMILY = 257,
			ARG_STATE = 258,
			ARG_YES,
		};
		static struct option long_opts[] = {
			{ "interactive", 0, 0, 'i' },
			{ "yes", 0, 0, ARG_YES },
			{ "quiet", 0, 0, 'q' },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "addr", 1, 0, 'a' },
			{ "lladdr", 1, 0, 'l' },
			{ "dev", 1, 0, 'd' },
			{ "family", 1, 0, ARG_FAMILY },
			{ "state", 1, 0, ARG_STATE },
			{ 0, 0, 0, 0 }
		};
	
		c = getopt_long(argc, argv, "qhva:l:d:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case 'i': interactive = 1; break;
		case ARG_YES: default_yes = 1; break;
		case 'q': quiet = 1; break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'a': nl_cli_neigh_parse_dst(neigh, optarg); break;
		case 'l': nl_cli_neigh_parse_lladdr(neigh, optarg); break;
		case 'd': nl_cli_neigh_parse_dev(neigh, link_cache, optarg); break;
		case ARG_FAMILY: nl_cli_neigh_parse_family(neigh, optarg); break;
		case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break;
		}
 	}

	nl_cache_foreach_filter(neigh_cache, OBJ_CAST(neigh), delete_cb, NULL);

	if (!quiet)
		printf("Deleted %d neighbours\n", deleted);

	return 0;
}
Example #5
0
int main(int argc, char *argv[])
{
	struct rtnl_qdisc *qdisc;
	struct rtnl_tc *tc;
	struct nl_cache *link_cache, *qdisc_cache;
 
	params.dp_fd = stdout;
	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	qdisc_cache = nl_cli_qdisc_alloc_cache(sock);
 	qdisc = nl_cli_qdisc_alloc();
	tc = (struct rtnl_tc *) qdisc;
 
	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_DETAILS = 257,
			ARG_STATS = 258,
		};
		static struct option long_opts[] = {
			{ "details", 0, 0, ARG_DETAILS },
			{ "stats", 0, 0, ARG_STATS },
			{ "recursive", 0, 0, 'r' },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "dev", 1, 0, 'd' },
			{ "parent", 1, 0, 'p' },
			{ "id", 1, 0, 'i' },
			{ "kind", 1, 0, 'k' },
			{ 0, 0, 0, 0 }
		};
	
		c = getopt_long(argc, argv, "rhvd:p:i:k:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break;
		case ARG_STATS: params.dp_type = NL_DUMP_STATS; break;
		case 'r': recursive = 1; break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
		case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
		case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
		case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
		}
 	}

	if (recursive)
		nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), list_qdisc, NULL);
	else
		nl_cache_dump_filter(qdisc_cache, &params, OBJ_CAST(qdisc));

	return 0;
}
Example #6
0
/**
 * Find object in cache
 * @arg cache           Cache
 * @arg filter          object acting as a filter
 *
 * Searches the cache for an object which matches the object filter.
 * nl_object_match_filter() is used to determine if the objects match.
 * If a matching object is found, the reference counter is incremented and the
 * object is returned.
 *
 * Therefore, if an object is returned, the reference to the object
 * must be returned by calling nl_object_put() after usage.
 *
 * @return Reference to object or NULL if not found.
 */
__attribute__((weak)) struct nl_object *
nl_cache_find(struct nl_cache *cache, struct nl_object *filter)
{
	struct nl_object *obj = NULL;

	/* obj will be set to point to the matched object, so if there are
	 * multiple matches, obj will be set to point to the last match.
	 */
	nl_cache_foreach_filter(cache, filter, cb_found_cache_obj, &obj);
	return obj;
}
Example #7
0
static void print_tc_childs(struct rtnl_tc *tc, void *arg)
{
	struct rtnl_class *filter;

	filter = nl_cli_class_alloc();

	rtnl_tc_set_parent(TC_CAST(filter), rtnl_tc_get_handle(tc));
	rtnl_tc_set_ifindex(TC_CAST(filter), rtnl_tc_get_ifindex(tc));

	nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), &print_class, arg);

	rtnl_class_put(filter);
}
Example #8
0
static void list_classes(int ifindex, uint32_t parent)
{
	struct nl_cache *class_cache;
	struct rtnl_class *filter = nl_cli_class_alloc();

	class_cache = nl_cli_class_alloc_cache(sock, ifindex);

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
	params.dp_prefix += NUM_INDENT;
	nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), list_class, NULL);
	params.dp_prefix -= NUM_INDENT;

	rtnl_class_put(filter);
	nl_cache_free(class_cache);
}
/**
 * Call a callback for each filter attached to the qdisc
 * @arg qdisc		the parent qdisc
 * @arg cache		a filter cache including at least all the filters
 *                      attached to the specified qdisc
 * @arg cb              callback function
 * @arg arg             argument to be passed to callback function
 */
void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
			    void (*cb)(struct nl_object *, void *), void *arg)
{
	struct rtnl_cls *filter;

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

	rtnl_cls_set_ifindex(filter, qdisc->q_ifindex);
	rtnl_cls_set_parent(filter, qdisc->q_parent);

	nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
	rtnl_cls_put(filter);
}
Example #10
0
static void list_qdiscs(int ifindex, uint32_t parent)
{
	struct nl_cache *qdisc_cache;
	struct rtnl_qdisc *filter = nl_cli_qdisc_alloc();

	qdisc_cache = nl_cli_qdisc_alloc_cache(sock);

	rtnl_tc_set_ifindex((struct rtnl_tc *) filter, ifindex);
	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
	params.dp_prefix += NUM_INDENT;
	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), list_qdisc, NULL);
	params.dp_prefix -= NUM_INDENT;

	rtnl_qdisc_put(filter);
	nl_cache_free(qdisc_cache);
}
Example #11
0
void dabbad_interface_statistics_get(Dabba__DabbaService_Service * service,
                                     const Dabba__InterfaceIdList * id_list,
                                     Dabba__InterfaceStatisticsList_Closure
                                     closure, void *closure_data)
{
    Dabba__InterfaceStatisticsList statistics_list =
        DABBA__INTERFACE_STATISTICS_LIST__INIT;
    Dabba__InterfaceStatisticsList *statistics_listp = NULL;
    struct nl_sock *sock = NULL;
    struct nl_cache *cache;
    struct rtnl_link *link;
    size_t a;

    assert(service);
    assert(closure_data);

    cache = link_cache_alloc(&sock);
    link = rtnl_link_alloc();

    if (!link || !cache)
        goto out;

    if (id_list->n_list) {
        for (a = 0; a < id_list->n_list; a++) {
            rtnl_link_set_name(link, id_list->list[a]->name);
            nl_cache_foreach_filter(cache, OBJ_CAST(link),
                                    __interface_statistics_get,
                                    &statistics_list);
        }
    } else
        nl_cache_foreach(cache, __interface_statistics_get,
                         &statistics_list);

    statistics_listp = &statistics_list;

out:
    closure(statistics_listp, closure_data);
    for (a = 0; a < statistics_list.n_list; a++) {
        free(statistics_list.list[a]->status);
        free(statistics_list.list[a]->id);
        free(statistics_list.list[a]);
    }
    free(statistics_list.list);
    link_destroy(link);
    link_cache_destroy(sock, cache);
}
static gboolean
deferred_emit_carrier_state (gpointer user_data)
{
	NMNetlinkMonitor *self = NM_NETLINK_MONITOR (user_data);
	NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
	int err;

	priv->request_status_id = 0;

	/* Update the link cache with latest state, and if there are no errors
	 * emit the link states for all the interfaces in the cache.
	 */
	err = nl_cache_refill (priv->nlh_sync, priv->link_cache);
	if (err < 0)
		nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror (err));
	else
		nl_cache_foreach_filter (priv->link_cache, NULL, link_msg_handler, self);

	return FALSE;
}
Example #13
0
int main(int argc, char *argv[])
{
	struct nl_sock *sock;
	struct nl_cache *link_cache;
	struct rtnl_link *link;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	link = nl_cli_link_alloc();

	for (;;) {
		int c, optidx = 0;
		static struct option long_opts[] = {
			{ "list", 0, 0, 'l' },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "name", 1, 0, 'n' },
			{ "index", 1, 0, 'i' },
			{ 0, 0, 0, 0 }
		};

		c = getopt_long(argc, argv, "lhvn:i:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case 'l': list_stat_names(); break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'n': nl_cli_link_parse_name(link, optarg); break;
		case 'i': nl_cli_link_parse_ifindex(link, optarg); break;
		}
	}

	gargc = argc;
	nl_cache_foreach_filter(link_cache, OBJ_CAST(link), dump_stats, argv);

	return 0;
}
Example #14
0
std::deque<rtnl_neigh *> nl_bridge::get_fdb_entries_of_port(rtnl_link *br_port,
                                                            uint16_t vid) {

  std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> filter(
      rtnl_neigh_alloc(), rtnl_neigh_put);

  rtnl_neigh_set_ifindex(filter.get(), rtnl_link_get_ifindex(br_port));
  rtnl_neigh_set_master(filter.get(), rtnl_link_get_ifindex(bridge));
  rtnl_neigh_set_vlan(filter.get(), vid);
  rtnl_neigh_set_family(filter.get(), AF_BRIDGE);

  std::deque<rtnl_neigh *> neighs;
  nl_cache_foreach_filter(
      nl->get_cache(cnetlink::NL_NEIGH_CACHE), OBJ_CAST(filter.get()),
      [](struct nl_object *o, void *arg) {
        std::deque<rtnl_neigh *> *neighs = (std::deque<rtnl_neigh *> *)arg;
        neighs->push_back(NEIGH_CAST(o));
        VLOG(3) << "needs to be updated " << o;
      },
      &neighs);

  return neighs;
}
Example #15
0
/*
 * Get the nexthop for the first default AF_INET route. Sets
 * *addr if found, caller must release reference to *addr. Returns 1 if an
 * error occurs, NULL *addr if no error but no AF_INET default route exists.
 */
static int get_default_gw_inet_addr(struct nl_sock *sk, struct nl_addr **addr)
{
    struct nl_cache *route_cache;
    int err;
    err = rtnl_route_alloc_cache(sk, AF_INET, 0, &route_cache);
    if (err < 0) {
        warnx("rtnl_addr_alloc_cache() failed: %s", nl_geterror(err));
        return 1;
    }

    /* Retrieve the first AF_INET default route. */
    struct rtnl_route *filter;
    filter = rtnl_route_alloc();
    assert(filter);
    rtnl_route_set_type(filter, 1); /* XXX RTN_UNICAST from linux/rtnetlink.h */
    struct nl_addr *filter_addr;
    err = nl_addr_parse("default", AF_INET, &filter_addr);
    if (err < 0) {
        warnx("nl_addr_parse(default) failed: %s", nl_geterror(err));

        rtnl_route_put(filter);
        nl_cache_free(route_cache);
        return 1;
    }
    rtnl_route_set_dst(filter, filter_addr);

    *addr = NULL;
    nl_cache_foreach_filter(route_cache, (struct nl_object *)filter,
            match_first_nh_gw, addr);

    /* No default gateway is not an error, so always return 0 here */
    nl_addr_put(filter_addr);
    rtnl_route_put(filter);
    nl_cache_free(route_cache);
    return 0;
}
Example #16
0
int main(int argc, char *argv[])
{
	struct nl_sock *nl_sock;
	struct nl_cache *link_cache;
	int ifindex;
	int ret = 0;
	int err = 0;

	if (argc < 2)
	{
		printf("%s ip gw on/off tip\n", argv[0]);
		return -1;
	}

//link
	if (err = rtnl_route_read_table_names(ROUTE_TABLE)) {
		printf("failed to read %s. err = %s\n", ROUTE_TABLE, nl_geterror(err));
		return -1;;
	}

	nl_sock = nl_socket_alloc();
	if (NULL == nl_sock) {
		printf("failed to alloc netlink handler.\n");
		return -1;
	}

	if (err = nl_connect(nl_sock, NETLINK_ROUTE)) {
		printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}

	if (err = rtnl_link_alloc_cache(nl_sock, AF_INET, &link_cache))
	{
		printf("failed to allocate link cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}

	ifindex = rtnl_link_name2i(link_cache, NAME);
	if (0 == ifindex) {
		printf("%s - failed to find.\n", NAME);
		ret = -1;
		goto release_link_cache;
	}

	struct rtnl_link * link = rtnl_link_get(link_cache, ifindex);
	if (link == NULL)
	{
		printf("can't get link.\n");
		ret = -1;
		goto release_link_cache;
	}
	//rtnl_link_get_by_name

	struct nl_addr *lladdr = rtnl_link_get_addr(link);
	if (NULL == lladdr || AF_LLC != nl_addr_get_family(lladdr)) {
		printf("failed to get MAC\n");
		ret = -1;
		goto release_link;
	}

	uint8_t mac_address[ETHER_ADDR_LEN];
	memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN);
	printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
		 mac_address[0],
		 mac_address[1],
		 mac_address[2],
		 mac_address[3],
		 mac_address[4],
		 mac_address[5]);

//addr 
	struct nl_cache * addr_cache;
	if (err  = rtnl_addr_alloc_cache(nl_sock, &addr_cache))
	{
		printf("fail to get addr_cache\n");
		ret = -1;
		goto release_link;
	}
	struct rtnl_addr *addr = rtnl_addr_alloc();
	rtnl_addr_set_ifindex(addr, ifindex);
	rtnl_addr_set_family(addr, AF_INET);
	int prefixlen = 16;
	nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, get_ip, &prefixlen);
	nl_cache_free(addr_cache);

	uint32_t ipaddr = inet_addr(argv[1]);
	struct nl_addr * local = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr));
	rtnl_addr_set_local(addr, local);
	rtnl_addr_set_ifindex(addr, ifindex);
	rtnl_addr_set_family(addr, AF_INET);
	rtnl_addr_set_prefixlen(addr, 32);

	if (!strcmp(argv[2], "on"))
	{
		if (err = rtnl_addr_add(nl_sock, addr, 0))
		{
			printf("fail to add addr %s\n", nl_geterror(err));
			ret = -1;
			goto release_addr;
		}
	}
	else
	{
		if (err = rtnl_addr_delete(nl_sock, addr, 0))
		{
			printf("fail to del addr %s\n", nl_geterror(err));
			ret = -1;
			goto release_addr;
		}
		
	}
//neigh
	struct nl_cache * neigh_cache;
	if (err = rtnl_neigh_alloc_cache(nl_sock, &neigh_cache))
	{
		printf("failed to allocate neighbor cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_neigh_cache;
	}

	uint32_t gw = inet_addr(argv[3]);
	struct nl_addr * gw_addr = nl_addr_build(AF_INET, &gw, sizeof(gw));

	struct rtnl_neigh * neigh = rtnl_neigh_get(neigh_cache, ifindex, gw_addr);
	if (neigh) {
		// It's optional
		struct nl_addr * lladdr = rtnl_neigh_get_lladdr(neigh);
		if (lladdr) {
			uint8_t mac_address[ETHER_ADDR_LEN];
			memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN);
			printf("gw  %02X:%02X:%02X:%02X:%02X:%02X\n",
		 		mac_address[0],
		 		mac_address[1],
		 		mac_address[2],
		 		mac_address[3],
		 		mac_address[4],
		 		mac_address[5]);
		}
	}

	nl_addr_put(gw_addr);

//route
	struct nl_cache *route_cache;
	if (err = rtnl_route_alloc_cache(nl_sock, AF_INET, 0, &route_cache))
	{
		printf("failed to allocate route cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_neigh_cache;
	}

	struct rtnl_route *route = rtnl_route_alloc();
	struct nl_addr * taddr;
	err = nl_addr_parse(argv[4], AF_INET, &taddr);
        if (err)
        {
                printf("failed to get taddr. err = %s\n", nl_geterror(err));
                ret = -1;
                goto release_route_cache;
                
        }

	nl_cache_foreach_filter(route_cache, OBJ_CAST(route), get_route, NULL);
/*
	struct nl_sock *nl_fib_sock;
	nl_fib_sock = nl_socket_alloc();
	if (err = nl_connect(nl_fib_sock, NETLINK_FIB_LOOKUP)) {
		printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}
	struct nl_dump_params params = {
		.dp_fd = stdout,
		.dp_type = NL_DUMP_DETAILS,
	};

	struct nl_cache *route_cache = flnl_result_alloc_cache();

        struct flnl_request *req = flnl_request_alloc();
        struct nl_addr * taddr;
	err = nl_addr_parse(argv[4], AF_INET, &taddr);
	if (err)
	{
		printf("failed to get taddr. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_route;
		
	}
	int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE;
        flnl_request_set_addr(req, taddr);
	flnl_request_set_table(req, table);
	flnl_request_set_scope(req, scope);
        err = flnl_lookup(nl_fib_sock, req, route_cache);
	if (err)
	{
		printf("failed to fib lookup. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_route_addr;
	}
	
	nl_cache_dump(route_cache, &params);

release_route_addr:
	nl_addr_put(taddr);	

release_route:
        nl_cache_free(route_cache);
	nl_object_put(OBJ_CAST(req));

	nl_close(nl_fib_sock);
	nl_socket_free(nl_fib_sock);
*/
release_route_cache:
	nl_cache_free(route_cache);
release_neigh_cache:
	nl_cache_free(neigh_cache);
release_addr:
	nl_addr_put(local);
	rtnl_addr_put(addr);
release_link:
	rtnl_link_put(link);
release_link_cache:
	nl_cache_free(link_cache);
release_nl:
	nl_close(nl_sock);
	nl_socket_free(nl_sock);

	return ret;
}
Example #17
0
/**
 * Query NETLINK for ethernet configuration
 *
 * @param ethinf Pointer to an available struct etherinfo element.  The 'device' member
 *               must contain a valid string to the device to query for information
 * @param nlc    Pointer to the libnl handle, which is used for the query against NETLINK
 * @param query  What to query for.  Must be NLQRY_LINK or NLQRY_ADDR.
 *
 * @return Returns 1 on success, otherwise 0.
 */
int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
{
	struct nl_cache *link_cache;
	struct nl_cache *addr_cache;
	struct rtnl_addr *addr;
	struct rtnl_link *link;
	struct etherinfo *ethinf = NULL;
	int ret = 0;

	if( !data || !data->ethinfo ) {
		return 0;
	}
	ethinf = data->ethinfo;

	/* Open a NETLINK connection on-the-fly */
	if( !open_netlink(data) ) {
		PyErr_Format(PyExc_RuntimeError,
			     "Could not open a NETLINK connection for %s",
			     ethinf->device);
		return 0;
	}

	/* Find the interface index we're looking up.
	 * As we don't expect it to change, we're reusing a "cached"
	 * interface index if we have that
	 */
	if( ethinf->index < 0 ) {
		link_cache = rtnl_link_alloc_cache(*data->nlc);
		ethinf->index = rtnl_link_name2i(link_cache, ethinf->device);
		if( ethinf->index < 0 ) {
			return 0;
		}
		nl_cache_free(link_cache);
	}

	/* Query the for requested info vai NETLINK */
	switch( query ) {
	case NLQRY_LINK:
		/* Extract MAC/hardware address of the interface */
		link_cache = rtnl_link_alloc_cache(*data->nlc);
		link = rtnl_link_alloc();
		rtnl_link_set_ifindex(link, ethinf->index);
		nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf);
		rtnl_link_put(link);
		nl_cache_free(link_cache);
		ret = 1;
		break;

	case NLQRY_ADDR:
		/* Extract IP address information */
		addr_cache = rtnl_addr_alloc_cache(*data->nlc);
		addr = rtnl_addr_alloc();
		rtnl_addr_set_ifindex(addr, ethinf->index);

                /* Make sure we don't have any old IPv6 addresses saved */
                if( ethinf->ipv6_addresses ) {
                        free_ipv6addresses(ethinf->ipv6_addresses);
                        ethinf->ipv6_addresses = NULL;
                }

                /* Retrieve all address information */
		nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf);
		rtnl_addr_put(addr);
		nl_cache_free(addr_cache);
		ret = 1;
		break;

	default:
		ret = 0;
	}
	return ret;
}
Example #18
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);
	}
}
Example #19
0
int main(int argc, char *argv[])
{
	struct nl_handle *nlh;
	struct nl_cache *link_cache, *route_cache;
	struct nl_addr *dst;
	struct rtnl_route *route;
        struct ip_lookup_res res;
	struct nl_dump_params params = {
		.dp_fd = stdout,
		.dp_type = NL_DUMP_FULL
	};
	int err = 1;

	if (argc < 2 || !strcmp(argv[1], "-h"))
		print_usage();

	if (nltool_init(argc, argv) < 0)
		goto errout;

	nlh = nltool_alloc_handle();
	if (!nlh)
		goto errout;

	route = rtnl_route_alloc();
	if (!route)
		goto errout_free_handle;

	if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
		goto errout_free_route;

	link_cache = nltool_alloc_link_cache(nlh);
	if (!link_cache)
		goto errout_close;

	dst = nltool_addr_parse(argv[1]);
	if (!dst)
		goto errout_link_cache;

	route_cache = nltool_alloc_route_cache(nlh);
	if (!route_cache)
		goto errout_addr_put;

	{
		struct nl_msg *m;
		struct rtmsg rmsg = {
			.rtm_family = nl_addr_get_family(dst),
			.rtm_dst_len = nl_addr_get_prefixlen(dst),
		};

		m = nlmsg_alloc_simple(RTM_GETROUTE, 0);
		nlmsg_append(m, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO);
		nla_put_addr(m, RTA_DST, dst);

		if ((err = nl_send_auto_complete(nlh, m)) < 0) {
			nlmsg_free(m);
			fprintf(stderr, "%s\n", nl_geterror());
			goto errout_route_cache;
		}

		nlmsg_free(m);

		nl_socket_modify_cb(nlh, NL_CB_VALID, NL_CB_CUSTOM, cb,
				 route_cache);

		if (nl_recvmsgs_default(nlh) < 0) {
			fprintf(stderr, "%s\n", nl_geterror());
			goto errout_route_cache;
		}
	}

        rtnl_route_set_dst(route, dst);
	nl_cache_dump_filter(route_cache, &params, (struct nl_object *) route);
        memset(&res, 0, sizeof(res));
        nl_cache_foreach_filter(route_cache, (struct nl_object *) route, route_proc_cb,
                                &res);

        printf("ip lookup result: oif idx: %d oif name %s ",
                res.oif, res.oifname);
        if (res.nh_addr) {
                char buf[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &res.nh_addr, buf, sizeof(buf));
                printf("via %s", buf);
        }
        printf ("\n");

	err = 0;
errout_route_cache:
	nl_cache_free(route_cache);
errout_addr_put:
	nl_addr_put(dst);
errout_link_cache:
	nl_cache_free(link_cache);
errout_close:
	nl_close(nlh);
errout_free_route:
        rtnl_route_put(route);
errout_free_handle:
	nl_handle_destroy(nlh);
errout:
	return err;
}
int main(int argc, char *argv[])
{
	struct rtnl_addr *addr;
	struct nl_cache *link_cache, *addr_cache;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	addr_cache = nl_cli_addr_alloc_cache(sock);
	addr = nl_cli_addr_alloc();

	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_FAMILY = 257,
			ARG_LABEL = 258,
			ARG_YES,
			ARG_PEER,
			ARG_SCOPE,
			ARG_BROADCAST,
			ARG_PREFERRED,
			ARG_VALID,
		};
		static struct option long_opts[] = {
			{ "interactive", 0, 0, 'i' },
			{ "yes", 0, 0, ARG_YES },
			{ "quiet", 0, 0, 'q' },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "local", 1, 0, 'a' },
			{ "dev", 1, 0, 'd' },
			{ "family", 1, 0, ARG_FAMILY },
			{ "label", 1, 0, ARG_LABEL },
			{ "peer", 1, 0, ARG_PEER },
			{ "scope", 1, 0, ARG_SCOPE },
			{ "broadcast", 1, 0, ARG_BROADCAST },
			{ "preferred", 1, 0, ARG_PREFERRED },
			{ "valid", 1, 0, ARG_VALID },
			{ 0, 0, 0, 0 }
		};
	
		c = getopt_long(argc, argv, "iqhva:d:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case 'i': interactive = 1; break;
		case ARG_YES: default_yes = 1; break;
		case 'q': quiet = 1; break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'a': nl_cli_addr_parse_local(addr, optarg); break;
		case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break;
		case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break;
		case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break;
		case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break;
		case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break;
		case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break;
		case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break;
		case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break;
		}
 	}

	nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), delete_cb, NULL);

	if (!quiet)
		printf("Deleted %d addresses\n", deleted);

	return 0;
}
Example #21
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);
}
Example #22
0
int main(int argc, char *argv[])
{
	struct rtnl_qdisc *qdisc;
	struct rtnl_tc *tc;
	struct nl_cache *link_cache, *qdisc_cache;
	int nfilter = 0;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	qdisc_cache = nl_cli_qdisc_alloc_cache(sock);
	qdisc = nl_cli_qdisc_alloc();
	tc = (struct rtnl_tc *) qdisc;

	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_YES = 257,
			ARG_INTERACTIVE = 258,
		};
		static struct option long_opts[] = {
			{ "interactive", 0, 0, ARG_INTERACTIVE },
			{ "yes", 0, 0, ARG_YES },
			{ "quiet", 0, 0, 'q' },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "dev", 1, 0, 'd' },
			{ "parent", 1, 0, 'p' },
			{ "id", 1, 0, 'i' },
			{ "kind", 1, 0, 'k' },
			{ 0, 0, 0, 0 }
		};

		c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case '?': nl_cli_fatal(EINVAL, "Invalid options");
		case ARG_INTERACTIVE: interactive = 1; break;
		case ARG_YES: default_yes = 1; break;
		case 'q': quiet = 1; break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'd':
			nfilter++;
			nl_cli_tc_parse_dev(tc, link_cache, optarg);
			break;
		case 'p':
			nfilter++;
			nl_cli_tc_parse_parent(tc, optarg);
			break;
		case 'i':
			nfilter++;
			nl_cli_tc_parse_handle(tc, optarg, 0);
			break;
		case 'k':
			nfilter++;
			nl_cli_tc_parse_kind(tc, optarg);
			break;
		}
	}

	if (nfilter == 0 && !interactive && !default_yes) {
		nl_cli_fatal(EINVAL,
			"You are attempting to delete all qdiscs on all devices.\n"
			"If you want to proceed, run nl-qdisc-delete --yes.\n"
			"Aborting...");
	}

	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), delete_cb, NULL);

	if (!quiet)
		printf("Deleted %d qdiscs\n", deleted);

	return 0;
}
Example #23
0
int main(int argc, char *argv[])
{
	struct nl_sock *sock;
	struct rtnl_addr *addr;
	struct nl_cache *link_cache, *addr_cache;
	struct nl_dump_params params = {
		.dp_type = NL_DUMP_LINE,
		.dp_nl_cb = print_prefix,
		.dp_fd = stdout,
	};
	int dump_env = 0;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	addr_cache = nl_cli_addr_alloc_cache(sock);
	addr = nl_cli_addr_alloc();

	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_FAMILY = 257,
			ARG_LABEL = 258,
			ARG_PEER,
			ARG_SCOPE,
			ARG_BROADCAST,
			ARG_DETAILS,
			ARG_ENV,
			ARG_PREFIX,
			ARG_PREFERRED,
			ARG_VALID,
		};
		static struct option long_opts[] = {
			{ "details", 0, 0, ARG_DETAILS },
			{ "env", 0, 0, ARG_ENV },
			{ "prefix", 1, 0, ARG_PREFIX },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "local", 1, 0, 'a' },
			{ "dev", 1, 0, 'd' },
			{ "family", 1, 0, ARG_FAMILY },
			{ "label", 1, 0, ARG_LABEL },
			{ "peer", 1, 0, ARG_PEER },
			{ "scope", 1, 0, ARG_SCOPE },
			{ "broadcast", 1, 0, ARG_BROADCAST },
			{ "preferred", 1, 0, ARG_PREFERRED },
			{ "valid", 1, 0, ARG_VALID },
			{ 0, 0, 0, 0 }
		};

		c = getopt_long(argc, argv, "46hva:d:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case '?': exit(NLE_INVAL);
		case '4': rtnl_addr_set_family(addr, AF_INET); break;
		case '6': rtnl_addr_set_family(addr, AF_INET6); break;
		case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break;
		case ARG_ENV: dump_env = 1; break;
		case ARG_PREFIX: prefix = strdup(optarg); break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'a': nl_cli_addr_parse_local(addr, optarg); break;
		case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break;
		case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break;
		case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break;
		case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break;
		case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break;
		case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break;
		case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break;
		case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break;
		}
	}

	if (dump_env)
		nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), env_dump,
					&params);
	else
		nl_cache_dump_filter(addr_cache, &params, OBJ_CAST(addr));

	return 0;
}
gboolean
nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self,
                                   guint32 ifindex,
                                   guint32 *ifflags,
                                   GError **error)
{
	NMNetlinkMonitorPrivate *priv;
	GetFlagsInfo info;
	struct rtnl_link *filter;
	int err;

	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE);
	g_return_val_if_fail (ifflags != NULL, FALSE);

	priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);

	/* Update the link cache with the latest information */
	err = nl_cache_refill (priv->nlh_sync, priv->link_cache);
	if (err < 0) {
		g_set_error (error,
		             NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE,
		             _("error updating link cache: %s"),
		             nl_geterror (err));
		return FALSE;
	}

	/* HACK: Apparently to get it working we have to refill the cache twice;
	 * otherwise some kernels (or maybe libnl?) only send a few of the
	 * interfaces in the refill request.
	 */
	if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) {
		g_set_error (error,
		             NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE,
		             _("error updating link cache: %s"),
		             nl_geterror (err));
		return FALSE;
	}

	/* Set up the filter */
	filter = rtnl_link_alloc ();
	if (!filter) {
		g_set_error (error,
		             NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_BAD_ALLOC,
		             _("error processing netlink message: %s"),
		             nl_geterror (err));
		return FALSE;
	}
	rtnl_link_set_ifindex (filter, ifindex);

	memset (&info, 0, sizeof (info));
	info.self = self;
	info.filter = filter;
	info.error = NULL;
	nl_cache_foreach_filter (priv->link_cache, NULL, get_flags_sync_cb, &info);

	rtnl_link_put (filter);

	if (info.error) {
		if (error)
			*error = info.error;
		else
			g_error_free (info.error);
		return FALSE;
	} else
		*ifflags = info.flags;

	return TRUE; /* success */
}
int main(int argc, char *argv[])
{
	struct nl_cache *link_cache, *route_cache;
	struct rtnl_route *route;
	int nf = 0;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	route_cache = nl_cli_route_alloc_cache(sock, 0);
	route = nl_cli_route_alloc();

	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_FAMILY = 257,
			ARG_SRC = 258,
			ARG_IIF,
			ARG_PREF_SRC,
			ARG_METRICS,
			ARG_PRIORITY,
			ARG_SCOPE,
			ARG_PROTOCOL,
			ARG_TYPE,
			ARG_YES,
		};
		static struct option long_opts[] = {
			{ "interactive", 0, 0, 'i' },
			{ "yes", 0, 0, ARG_YES },
			{ "quiet", 0, 0, 'q' },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "dst", 1, 0, 'd' },
			{ "nexthop", 1, 0, 'n' },
			{ "table", 1, 0, 't' },
			{ "family", 1, 0, ARG_FAMILY },
			{ "src", 1, 0, ARG_SRC },
			{ "iif", 1, 0, ARG_IIF },
			{ "pref-src", 1, 0, ARG_PREF_SRC },
			{ "metrics", 1, 0, ARG_METRICS },
			{ "priority", 1, 0, ARG_PRIORITY },
			{ "scope", 1, 0, ARG_SCOPE },
			{ "protocol", 1, 0, ARG_PROTOCOL },
			{ "type", 1, 0, ARG_TYPE },
			{ 0, 0, 0, 0 }
		};

		c = getopt_long(argc, argv, "iqhvd:n:t:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case 'i': interactive = 1; break;
		case ARG_YES: default_yes = 1; break;
		case 'q': quiet = 1; break;
		case 'h': print_usage(); break;
		case 'v': print_version(); break;
		case 'd': nf++; nl_cli_route_parse_dst(route, optarg); break;
		case 'n': nf++; nl_cli_route_parse_nexthop(route, optarg, link_cache); break;
		case 't': nf++; nl_cli_route_parse_table(route, optarg); break;
		case ARG_FAMILY: nf++; nl_cli_route_parse_family(route, optarg); break;
		case ARG_SRC: nf++; nl_cli_route_parse_src(route, optarg); break;
		case ARG_IIF: nf++; nl_cli_route_parse_iif(route, optarg, link_cache); break;
		case ARG_PREF_SRC: nf++; nl_cli_route_parse_pref_src(route, optarg); break;
		case ARG_METRICS: nf++; nl_cli_route_parse_metric(route, optarg); break;
		case ARG_PRIORITY: nf++; nl_cli_route_parse_prio(route, optarg); break;
		case ARG_SCOPE: nf++; nl_cli_route_parse_scope(route, optarg); break;
		case ARG_PROTOCOL: nf++; nl_cli_route_parse_protocol(route, optarg); break;
		case ARG_TYPE: nf++; nl_cli_route_parse_type(route, optarg); break;
		}
	}

	if (nf == 0 && !interactive && !default_yes) {
		fprintf(stderr, "You attempted to delete all routes in "
			"non-interactive mode, aborting.\n");
		exit(0);
	}

	nl_cache_foreach_filter(route_cache, OBJ_CAST(route), delete_cb, NULL);

	if (!quiet)
		printf("Deleted %d routes\n", deleted);

	return 0;
}
Example #26
0
void nl_bridge::update_vlans(rtnl_link *old_link, rtnl_link *new_link) {
  assert(sw);
  assert(bridge); // already checked

  rtnl_link_bridge_vlan *old_br_vlan, *new_br_vlan;
  rtnl_link *_link;

  if (old_link == nullptr) {
    // link added
    old_br_vlan = &empty_br_vlan;
    new_br_vlan = rtnl_link_bridge_get_port_vlan(new_link);
    _link = nl->get_link(rtnl_link_get_ifindex(new_link), AF_UNSPEC);
  } else if (new_link == nullptr) {
    // link deleted
    old_br_vlan = rtnl_link_bridge_get_port_vlan(old_link);
    new_br_vlan = &empty_br_vlan;
    _link = nl->get_link(rtnl_link_get_ifindex(old_link), AF_UNSPEC);
  } else {
    // link updated
    old_br_vlan = rtnl_link_bridge_get_port_vlan(old_link);
    new_br_vlan = rtnl_link_bridge_get_port_vlan(new_link);
    _link = nl->get_link(rtnl_link_get_ifindex(new_link), AF_UNSPEC);
  }

  if (old_br_vlan == nullptr) {
    old_br_vlan = &empty_br_vlan;
  }

  if (new_br_vlan == nullptr) {
    new_br_vlan = &empty_br_vlan;
  }

  if (_link == nullptr) {
    // XXX FIXME in case a vxlan has been deleted the vxlan_domain and
    // vxlan_dom_bitmap need an update, maybe this can be handled already from
    // the link_deleted of the vxlan itself?
    LOG(WARNING) << __FUNCTION__
                 << ": could not get parent link of bridge interface. This "
                    "case needs further checks if everything got already "
                    "deleted.";
    return;
  }

  // check for vid changes
  if (br_vlan_equal(old_br_vlan, new_br_vlan)) {
    VLOG(2) << __FUNCTION__ << ": vlans did not change";
    return;
  }

  link_type lt = get_link_type(_link);
  uint32_t pport_no = 0;
  uint32_t tunnel_id = -1;
  std::deque<rtnl_link *> bridge_ports;

  if (lt == LT_VXLAN) {
    assert(nl);
    nl->get_bridge_ports(rtnl_link_get_master(_link), &bridge_ports);

    if (vxlan->get_tunnel_id(_link, nullptr, &tunnel_id) != 0) {
      LOG(ERROR) << __FUNCTION__ << ": failed to get vni of link "
                 << OBJ_CAST(_link);
    }

  } else {
    pport_no = nl->get_port_id(rtnl_link_get_ifindex(_link));
    if (pport_no == 0) {
      LOG(ERROR) << __FUNCTION__
                 << ": invalid pport_no=0 of link: " << OBJ_CAST(_link);
      return;
    }
  }

  for (int k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
    int base_bit;
    uint32_t a = old_br_vlan->vlan_bitmap[k];
    uint32_t b = new_br_vlan->vlan_bitmap[k];
    uint32_t vlan_diff = a ^ b;

#if 0  // untagged change not yet implemented
    uint32_t c = old_br_vlan->untagged_bitmap[k];
    uint32_t d = new_br_vlan->untagged_bitmap[k];
    uint32_t untagged_diff = c ^ d;
#endif // 0

    base_bit = k * 32;
    int i = -1;
    int done = 0;
    while (!done) {
      int j = find_next_bit(i, vlan_diff);
      if (j > 0) {
        // vlan added or removed
        int vid = j - 1 + base_bit;
        bool egress_untagged = false;

        // check if egress is untagged
        if (new_br_vlan->untagged_bitmap[k] & 1 << (j - 1)) {
          egress_untagged = true;

#if 0  // untagged change not yet implemented
       // clear untagged_diff bit
          untagged_diff &= ~((uint32_t)1 << (j - 1));
#endif // 0
        }

        if (new_br_vlan->vlan_bitmap[k] & 1 << (j - 1)) {
          // vlan added
          if (lt == LT_VXLAN) {
            // update vxlan domain
            if (!is_vid_set(vid, vxlan_dom_bitmap)) {
              VLOG(1) << __FUNCTION__ << ": new vxlan domain vid=" << vid
                      << ", tunnel_id=" << tunnel_id;

              vxlan_domain.emplace(vid, tunnel_id);
              set_vid(vid, vxlan_dom_bitmap);
            } else {
              // XXX TODO check the map
            }

            // update all bridge ports to be access ports
            update_access_ports(_link, new_link ? new_link : old_link, vid,
                                tunnel_id, bridge_ports, true);
          } else {
            assert(pport_no);
            if (is_vid_set(vid, vxlan_dom_bitmap)) {
              // configure as access port
              std::string port_name = std::string(rtnl_link_get_name(_link));
              auto vxd_it = vxlan_domain.find(vid);

              if (vxd_it != vxlan_domain.end()) {
                vxlan->create_access_port((new_link) ? new_link : old_link,
                                          vxd_it->second, port_name, pport_no,
                                          vid, egress_untagged, nullptr);
              } else {
                LOG(FATAL) << __FUNCTION__
                           << ": should not happen, something is broken";
              }
            } else {
              // normal vlan port
              VLOG(3) << __FUNCTION__ << ": add vid=" << vid
                      << " on pport_no=" << pport_no
                      << " link: " << OBJ_CAST(_link);
              sw->egress_bridge_port_vlan_add(pport_no, vid, egress_untagged);
              sw->ingress_port_vlan_add(pport_no, vid,
                                        new_br_vlan->pvid == vid);
            }
          }
        } else {
          // vlan removed
          if (lt == LT_VXLAN) {
            unset_vid(vid, vxlan_dom_bitmap);
            vxlan_domain.erase(vid);

            // update all bridge ports to be normal bridge ports
            update_access_ports(_link, new_link ? new_link : old_link, vid,
                                tunnel_id, bridge_ports, false);
          } else {
            VLOG(3) << __FUNCTION__ << ": remove vid=" << vid
                    << " on pport_no=" << pport_no
                    << " link: " << OBJ_CAST(_link);
            sw->ingress_port_vlan_remove(pport_no, vid,
                                         old_br_vlan->pvid == vid);

            // delete all FM pointing to this group first
            sw->l2_addr_remove_all_in_vlan(pport_no, vid);

            std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> filter(
                rtnl_neigh_alloc(), rtnl_neigh_put);

            rtnl_neigh_set_ifindex(filter.get(), rtnl_link_get_ifindex(bridge));
            rtnl_neigh_set_master(filter.get(), rtnl_link_get_master(bridge));
            rtnl_neigh_set_family(filter.get(), AF_BRIDGE);
            rtnl_neigh_set_vlan(filter.get(), vid);
            rtnl_neigh_set_flags(filter.get(), NTF_MASTER | NTF_EXT_LEARNED);
            rtnl_neigh_set_state(filter.get(), NUD_REACHABLE);

            nl_cache_foreach_filter(l2_cache.get(), OBJ_CAST(filter.get()),
                                    [](struct nl_object *o, void *arg) {
                                      VLOG(3) << "l2_cache remove object " << o;
                                      nl_cache_remove(o);
                                    },
                                    nullptr);

            sw->egress_bridge_port_vlan_remove(pport_no, vid);
          }
        }

        i = j;
      } else {
        done = 1;
      }
    }

#if 0 // not yet implemented the update
		done = 0;
		i = -1;
		while (!done) {
			// vlan is existing, but swapping egress tagged/untagged
			int j = find_next_bit(i, untagged_diff);
			if (j > 0) {
				// egress untagged changed
				int vid = j - 1 + base_bit;
				bool egress_untagged = false;

				// check if egress is untagged
				if (new_br_vlan->untagged_bitmap[k] & 1 << (j-1)) {
					egress_untagged = true;
				}

				// XXX implement update
				fm_driver.update_port_vid_egress(devname, vid, egress_untagged);


				i = j;
			} else {
				done = 1;
			}
		}
#endif
  }
}