example code: my_nl_cache_exclude_non_matching(...)

Pedro Francisco pedrogfrancisco at gmail.com
Tue Mar 30 20:02:38 EDT 2010


For the sake of completeness, since I couldn't use
* cache_subset() nor
* tricks with nl_cache_move() nor
* other tricks with callbacks
in order to get a subset of a cache which only had the interfaces which 
matched a filter (see my previous mail: the interfaces' addresses at the second 
cache would appear as "none"), I created the
void my_nl_cache_exclude_non_matching(struct nl_cache *target, struct 
rtnl_addr* filter)


my_nl_cache_exclude_non_matching(...) strips all the interfaces from a cache 
which don't verify a certain condition. It doesn't create a copy of the cache, 
it strips of the cache which is provided as parameter those rtnl_addr not 
matching the filter.

In the event anyone else has the same problem, here it is. I hope it is 
useful.

It's available together with example code on http://pastebin.com/pmYFTPUQ or 
below:

#include <stdio.h>
#include <assert.h>

#include <netlink/route/link.h>
#include <netlink/route/addr.h>

void my_nl_cache_exclude_non_matching(struct nl_cache *target, struct 
rtnl_addr* filter);

/* too much information */
//int nl_debug = 1;
//#define VERBOSE_ERRORS 1


int main(int argc, char *argv[])
{
    struct nl_handle *nlh = NULL;
    struct nl_cache *link_cache = NULL;
    struct nl_cache *addr_cache = NULL;
    struct nl_cache *filtered_cache = NULL;
    struct rtnl_addr *addr = NULL;
    struct nl_dump_params params;
    int err = 1;

    nlh = nl_handle_alloc();
    if (!nlh)
	return -1;

    addr = rtnl_addr_alloc();
    if (!addr)
	return -1;

    if (nl_connect(nlh, NETLINK_ROUTE) < 0)
	assert(0);


    link_cache = rtnl_link_alloc_cache(nlh);
    if (!link_cache)
	assert(0);
    
    nl_cache_mngt_provide(link_cache);
    
    addr_cache = rtnl_addr_alloc_cache(nlh);
    if (!addr_cache)
	assert(0);

    filtered_cache = rtnl_addr_alloc_cache(nlh);
    if (!filtered_cache)
	assert(0);

    // leave just eth0: set the filter `addr'
    rtnl_addr_set_ifindex(addr, if_nametoindex("eth0"));

    params.dp_type = NL_DUMP_BRIEF;
    params.dp_prefix = 30;
    params.dp_print_index = 1;
    params.dp_dump_msgtype = 1;
    params.dp_cb = NULL;
    params.dp_nl_cb = NULL;
    params.dp_data = NULL;
    params.dp_fd = stdout;
    params.dp_buf = NULL;
    params.dp_buflen = 0;

    printf("--------------------------------------\n");
    printf("original addr_cache dump-to-screen:\n");
    nl_cache_dump (addr_cache, &params);
    printf("--------------------------------------\n\n\n");
    perror(nl_geterror());


    printf("--------------------------------------\n");
    printf("after my_nl_cache_exclude_non_matching:\n");
    my_nl_cache_exclude_non_matching(filtered_cache, addr);
    nl_cache_dump (filtered_cache, &params);
    printf("--------------------------------------\n");
    perror(nl_geterror());
    err = 0;



    /* lots of free missing:
	nl_cache_free(filtered_cache);
	nl_cache_free(addr_cache);
	nl_cache_free(link_cache);
	nl_close(nlh);
	rtnl_addr_put(addr); */
    errout:
	return err;
}

void my_nl_cache_exclude_non_matching(struct nl_cache *target, struct 
rtnl_addr* filter)
{
    void my_cb_mark_matches(struct nl_object *obj, void *userdata)
    {
	nl_object_mark(obj);
    }

    void my_cb_exclude_non_matching(struct nl_object *obj, void *userdata)
    {
	if (nl_object_is_marked(obj) == 0)
	    nl_cache_remove(obj);
	else
	    nl_object_unmark(obj);
    }

    nl_cache_foreach_filter(target, (struct nl_object* ) filter, 
my_cb_mark_matches, NULL);
    nl_cache_foreach(target, my_cb_exclude_non_matching, NULL);
}

--
Pedro



More information about the libnl mailing list