I'm trying to set the IPv6 address of an interface, using libnl
.
Going through the documentation and other resources, this is basically what I'm trying to do:
static int set_ipv6(const char *if_name, const char *ipv6) {
struct rtnl_link *link = NULL;
struct nl_sock *sk = NULL;
struct rtnl_addr *ipv6_addr = NULL;
struct nl_addr* lo_ipv6_addr = NULL;
struct nl_cache *link_cache = NULL;
int err = 0;
int ifindex = 0;
sk = nl_socket_alloc();
if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) {
nl_perror(err, "nl_connect");
return err;
}
ipv6_addr = rtnl_addr_alloc();
if ((err = nl_addr_parse(ipv6, AF_INET6, &lo_ipv6_addr)) < 0) {
nl_perror(err, "nl_addr_parse");
return err;
}
printf("This part segfaults\n");
if((err = rtnl_addr_set_local(ipv6_addr, lo_ipv6_addr)) < 0) {
nl_perror(err, "rtnl_addr_set_local");
return err;
}
if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) {
nl_perror(err, "rtnl_link_alloc_cache");
return err;
}
if((link = rtnl_link_get_by_name(link_cache, if_name)) == NULL) {
return -1;
}
if((ifindex = rtnl_link_get_ifindex(link)) == 0) {
fprintf(stderr,"index of %s not set\n", if_name);
return -1;
}
rtnl_addr_set_ifindex(ipv6_addr, ifindex);
rtnl_addr_set_link(ipv6_addr, link);
if ((err = rtnl_addr_add(sk, ipv6_addr, 0)) < 0) {
nl_perror(err, "rtnl_addr_add");
return err;
}
nl_addr_put(lo_ipv6_addr);
rtnl_addr_put(ipv6_addr);
nl_cache_free(link_cache);
nl_socket_free(sk);
rtnl_link_put(link);
return 0;
}
Obviously, I call this code with something like:
set_ipv6("veth1", "fc00:dead:cafe:1::2");
Where veth1 is a valid veth device.
However, for some odd reason, this code seems to segfault as soon as rtnl_addr_set_local
is called, as it attempts to dereference an invalid address in the rdi
register, when setting up the stack.
Any ideas what might be wrong or could this possibly be a bug in libnl
?
Thanks!
Figured it out, it seems I was missing an include directive, more specifically - the addr.h header.
#include <netlink/route/addr.h>