/**
 * nm_netlink_foreach_route:
 * @ifindex: the interface index to filter routes for
 * @family: the address family to filter routes for
 * @scope: route scope, eg RT_SCOPE_LINK
 * @ignore_inet6_ll_mc: if %TRUE ignore IPv6 link-local and multi-cast routes
 * @callback: function called when a route matches the filter
 * @user_data: data passed to @callback
 *
 * Filters each route in the routing table against the given @ifindex and
 * @family (if given) and calls @callback for each matching route.
 *
 * Returns: a route if @callback returned one; the caller must dispose of the
 * route using rtnl_route_put() when it is no longer required.
 **/
struct rtnl_route *
nm_netlink_foreach_route (int ifindex,
                          int family,
                          int scope,
                          gboolean ignore_inet6_ll_mc,
                          NlRouteForeachFunc callback,
                          gpointer user_data)
{
	struct nl_cache *cache;
	ForeachRouteInfo info;

	memset (&info, 0, sizeof (info));
	info.ifindex = ifindex;
	info.family = family;
	info.scope = scope;
	info.ignore_inet6_ll_mc = ignore_inet6_ll_mc;
	info.callback = callback;
	info.user_data = user_data;
	info.iface = nm_netlink_index_to_iface (ifindex);

	rtnl_route_alloc_cache (nm_netlink_get_default_handle (), family, 0, &cache);
	g_warn_if_fail (cache != NULL);
	if (cache) {
		nl_cache_foreach (cache, foreach_route_cb, &info);
		nl_cache_free (cache);
	}
	g_free (info.iface);
	return info.out_route;
}
Exemple #2
0
static void
nm_ip6_manager_init (NMIP6Manager *manager)
{
	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);

	priv->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal,
	                                       NULL,
	                                       (GDestroyNotify) nm_ip6_device_destroy);

	priv->monitor = nm_netlink_monitor_get ();
	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_IFADDR, NULL);
	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_PREFIX, NULL);
	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_ROUTE, NULL);
	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_ND_USEROPT, NULL);
	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL);

	priv->netlink_id = g_signal_connect (priv->monitor, "notification",
	                                     G_CALLBACK (netlink_notification), manager);

	priv->nlh = nm_netlink_get_default_handle ();
	rtnl_addr_alloc_cache (priv->nlh, &priv->addr_cache);
	g_warn_if_fail (priv->addr_cache != NULL);
	rtnl_route_alloc_cache (priv->nlh, NETLINK_ROUTE, NL_AUTO_PROVIDE, &priv->route_cache);
	g_warn_if_fail (priv->route_cache != NULL);
}
struct nl_cache *nltool_alloc_route_cache(struct nl_handle *nlh)
{
	struct nl_cache *cache;

	cache = rtnl_route_alloc_cache(nlh);
	if (!cache)
		fprintf(stderr, "Unable to retrieve route cache: %s\n",
			nl_geterror());
	else
		nl_cache_mngt_provide(cache);

	return cache;
}
/*
 * 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;
}
Exemple #5
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;
}
Exemple #6
0
CAMLprim value
ocaml_get_routing_table(value unit) {
    CAMLparam1(unit);
    CAMLlocal3( ret, tmp, entry );

    struct nl_sock *fd;
    struct nl_cache *res, *links;
    struct rtnl_route *it;
    uint32 i_ip, netmask = 0, mask_len, gw;
    int i;
    struct nl_addr *ip;
    char device_name[IFNAMSIZ];
    struct rtnl_nexthop *to;
    fd = nl_socket_alloc();
    if (!fd) {
        fprintf(stderr, "error nl_socket_alloc\n");
        exit(1);
    }

    if(nl_connect(fd, NETLINK_ROUTE) < 0) {
        fprintf(stderr, "error nl_connect\n");
        exit(1);
    }

    ret = Val_emptylist;

    if(rtnl_route_alloc_cache(fd, AF_UNSPEC, 0, &res) < 0) {
        fprintf(stderr, "error rtnl_route_alloc_cache");
        exit(1);
    }

    if(rtnl_link_alloc_cache (fd, AF_UNSPEC, &links) < 0) {
        fprintf(stderr, "error rtnl_link_alloc_cache");
        exit(1);
    }

    it = (struct rtnl_route *)nl_cache_get_first(res);
    for(; it != NULL; it = (struct rtnl_route *)
                           nl_cache_get_next((struct nl_object *)it) ) {
        if(rtnl_route_get_family (it) == AF_INET) {
            ip = rtnl_route_get_dst(it);
            i_ip = ntohl(*(int *)nl_addr_get_binary_addr(ip));
            mask_len = nl_addr_get_prefixlen(ip);
            for(i = 0; i < 32; i++)
                netmask = (netmask << 1) + (i< mask_len?1:0);
            to = rtnl_route_nexthop_n(it, 0);
            rtnl_link_i2name(links, rtnl_route_nh_get_ifindex(to),
                             device_name, IFNAMSIZ);
            if ( rtnl_route_nh_get_gateway (to) != NULL)
                gw = ntohl(*(int *)nl_addr_get_binary_addr(
                               rtnl_route_nh_get_gateway (to)));
            else
                gw = 0;
            /*printf("src ip:%x mask:%x gw:%x dev:%s\n", i_ip, netmask, */
            /*gw, device_name);*/

            entry = caml_alloc(7,0);
            Store_field(entry, 0, Val_int(i_ip & 0xFFFF));
            Store_field(entry, 1, Val_int(i_ip >> 16));
            Store_field(entry, 2, Val_int(netmask & 0xFFFF));
            Store_field(entry, 3, Val_int(netmask >> 16));
            Store_field(entry, 4, Val_int(gw & 0xFFFF));
            Store_field(entry, 5, Val_int(gw >> 16));
            Store_field(entry, 6, caml_copy_string(device_name));

            // store in list
            tmp =  caml_alloc(2, 0);
            Store_field( tmp, 0, entry);  // head
            Store_field( tmp, 1, ret);  // tail
            ret = tmp;
        }
    }