diff --git a/vis/vis.c b/vis/vis.c
index beaeca1..37956b1 100644
--- a/vis/vis.c
+++ b/vis/vis.c
@@ -372,70 +372,146 @@ static void clear_lists(struct globals *globals)
 	}
 }
 
-static int register_interfaces(struct globals *globals)
+static int query_rtnl_link(int ifindex, nl_recvmsg_msg_cb_t func, void *arg)
 {
-	DIR *iface_base_dir;
-	struct dirent *iface_dir;
-	char *path_buff, *file_content;
-	char *content_newline;
+	struct ifinfomsg rt_hdr = {
+		.ifi_family = IFLA_UNSPEC,
+	};
+	struct nl_sock *sock;
+	struct nl_msg *msg;
+	struct nl_cb *cb;
+	int err = 0;
+	int ret;
 
-	path_buff = malloc(PATH_BUFF_LEN);
-	if (!path_buff) {
-		perror("Error - could not allocate path buffer");
-		goto err;
+	sock = nl_socket_alloc();
+	if (!sock)
+		return -ENOMEM;
+
+	ret = nl_connect(sock, NETLINK_ROUTE);
+	if (ret < 0) {
+		err = -ENOMEM;
+		goto err_free_sock;
 	}
 
-	iface_base_dir = opendir(SYS_IFACE_PATH);
-	if (!iface_base_dir) {
-		fprintf(stderr, "Error - the directory '%s' could not be read: %s\n",
-		       SYS_IFACE_PATH, strerror(errno));
-		fprintf(stderr, "Is the batman-adv module loaded and sysfs mounted ?\n");
-		goto err_buff;
+	cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!cb) {
+		err = -ENOMEM;
+		goto err_free_sock;
 	}
 
-	while ((iface_dir = readdir(iface_base_dir)) != NULL) {
-		snprintf(path_buff, PATH_BUFF_LEN, SYS_MESH_IFACE_FMT, iface_dir->d_name);
-		file_content = read_file(path_buff);
-		if (!file_content)
-			continue;
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, func, arg);
 
-		if (file_content[strlen(file_content) - 1] == '\n')
-			file_content[strlen(file_content) - 1] = '\0';
+	msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP);
+	if (!msg) {
+		err = -ENOMEM;
+		goto err_free_cb;
+	}
 
-		if (strcmp(file_content, "none") == 0)
-			goto free_line;
+	ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO);
+	if (ret < 0) {
+		err = -ENOMEM;
+		goto err_free_msg;
+	}
 
-		if (strcmp(file_content, globals->interface) != 0)
-			goto free_line;
+	ret = nla_put_u32(msg, IFLA_MASTER, ifindex);
+	if (ret < 0) {
+		err = -ENOMEM;
+		goto err_free_msg;
+	}
 
-		free(file_content);
-		file_content = NULL;
+	ret = nl_send_auto_complete(sock, msg);
+	if (ret < 0)
+		goto err_free_msg;
 
-		snprintf(path_buff, PATH_BUFF_LEN, SYS_IFACE_STATUS_FMT, iface_dir->d_name);
-		file_content = read_file(path_buff);
-		if (!file_content)
-			continue;
+	nl_recvmsgs(sock, cb);
 
-		content_newline = strstr(file_content, "\n");
-		if (content_newline)
-			*content_newline = '\0';
+err_free_msg:
+	nlmsg_free(msg);
+err_free_cb:
+	nl_cb_put(cb);
+err_free_sock:
+	nl_socket_free(sock);
 
-		if (strcmp(file_content, "active") == 0)
-			get_if_index_byname(globals, iface_dir->d_name);
+	return err;
+}
 
-free_line:
-		free(file_content);
-		file_content = NULL;
-	}
+struct register_interfaces_rtnl_arg {
+	struct globals *globals;
+	int ifindex;
+};
 
-	free(path_buff);
-	closedir(iface_base_dir);
-	return EXIT_SUCCESS;
+static struct nla_policy link_policy[IFLA_MAX + 1] = {
+	[IFLA_IFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ },
+	[IFLA_MASTER] = { .type = NLA_U32 },
+};
+
+static int register_interfaces_rtnl_parse(struct nl_msg *msg, void *arg)
+{
+	struct register_interfaces_rtnl_arg *register_arg = arg;
+	struct nlattr *attrs[IFLA_MAX + 1];
+	char path_buff[PATH_BUFF_LEN];
+	struct ifinfomsg *ifm;
+	char *content_newline;
+	char *file_content;
+	char *ifname;
+	int master;
+	int ret;
+
+	ifm = nlmsg_data(nlmsg_hdr(msg));
+	ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*ifm), attrs, IFLA_MAX,
+			  link_policy);
+	if (ret < 0)
+		goto err;
+
+	if (!attrs[IFLA_IFNAME])
+		goto err;
+
+	if (!attrs[IFLA_MASTER])
+		goto err;
+
+	ifname = nla_get_string(attrs[IFLA_IFNAME]);
+	master = nla_get_u32(attrs[IFLA_MASTER]);
+
+	/* required on older kernels which don't prefilter the results */
+	if (master != register_arg->ifindex)
+		goto err;
+
+	snprintf(path_buff, PATH_BUFF_LEN, SYS_IFACE_STATUS_FMT, ifname);
+	file_content = read_file(path_buff);
+	if (!file_content)
+		goto free_file;
+
+	content_newline = strstr(file_content, "\n");
+	if (content_newline)
+		*content_newline = '\0';
+
+	if (strcmp(file_content, "active") != 0)
+		goto err;
+
+	get_if_index_byname(register_arg->globals, ifname);
 
-err_buff:
-	free(path_buff);
+free_file:
+	free(file_content);
+	file_content = NULL;
 err:
-	return EXIT_FAILURE;
+	return NL_OK;
+}
+
+static int register_interfaces(struct globals *globals)
+{
+	struct register_interfaces_rtnl_arg register_arg = {
+		.globals = globals,
+	};
+
+	register_arg.ifindex = if_nametoindex(globals->interface);
+	if (!globals->interface)
+		return EXIT_FAILURE;
+
+
+	query_rtnl_link(register_arg.ifindex, register_interfaces_rtnl_parse,
+			&register_arg);
+
+	return EXIT_SUCCESS;
 }
 
 static const int parse_orig_list_mandatory[] = {
diff --git a/vis/vis.h b/vis/vis.h
index 178406c..36bdecc 100644
--- a/vis/vis.h
+++ b/vis/vis.h
@@ -25,7 +25,6 @@
 
 #define SYS_IFACE_PATH				"/sys/class/net"
 #define DEBUG_BATIF_PATH_FMT			"%s/batman_adv/%s"
-#define SYS_MESH_IFACE_FMT			SYS_IFACE_PATH"/%s/batman_adv/mesh_iface"
 #define SYS_IFACE_STATUS_FMT			SYS_IFACE_PATH"/%s/batman_adv/iface_status"
 
 
