From: Serhey Popovych <serhe.popovych@gmail.com>
To: netdev@vger.kernel.org
Subject: [RFC][PATCH iproute2-next 6/6] tuntap: Use netlink to walk through tuntap list
Date: Thu, 1 Feb 2018 21:40:58 +0200 [thread overview]
Message-ID: <1517514058-23596-7-git-send-email-serhe.popovych@gmail.com> (raw)
In-Reply-To: <1517514058-23596-1-git-send-email-serhe.popovych@gmail.com>
It seems bad idea to depend on sysfs being mounted and reflected to the
current network namespace. Same applies to procfs.
Instead netlink should be used to talk to the kernel and get list of
specific network devices among with their parameters.
Support for kernel netlink message filtering by passing IFLA_INFO_KIND
in RTM_GETLINK request: if kernel does not support filtering by the kind
we will check it in reply anyway. Check for ifi->ifi_type to be either
ARPHRD_NONE or ARPHRD_ETHER to seed up things a bit without kernel level
filtering.
Unfortunately tun driver does not implement dumping it's configuration
via netlink and we still need to use read_prop() which depends on sysfs
to get additional tun device information.
Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
ip/iptuntap.c | 121 +++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 91 insertions(+), 30 deletions(-)
diff --git a/ip/iptuntap.c b/ip/iptuntap.c
index 09f2be2..4628db2 100644
--- a/ip/iptuntap.c
+++ b/ip/iptuntap.c
@@ -20,6 +20,7 @@
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
+#include <linux/if_arp.h>
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
@@ -31,6 +32,8 @@
#include "utils.h"
#include "ip_common.h"
+static const char drv_name[] = "tun";
+
#define TUNDEV "/dev/net/tun"
static void usage(void) __attribute__((noreturn));
@@ -348,43 +351,101 @@ next:
globfree(&globbuf);
}
+static int tuntap_filter_req(struct nlmsghdr *nlh, int reqlen)
+{
+ struct rtattr *linkinfo;
+ int err;
-static int do_show(int argc, char **argv)
+ linkinfo = addattr_nest(nlh, reqlen, IFLA_LINKINFO);
+
+ err = addattr_l(nlh, reqlen, IFLA_INFO_KIND,
+ drv_name, sizeof(drv_name) - 1);
+ if (err)
+ return err;
+
+ addattr_nest_end(nlh, linkinfo);
+
+ return 0;
+}
+
+static int print_tuntap(const struct sockaddr_nl *who,
+ struct nlmsghdr *n, void *arg)
{
- DIR *dir;
- struct dirent *d;
+ struct ifinfomsg *ifi = NLMSG_DATA(n);
+ struct rtattr *tb[IFLA_MAX+1];
+ struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+ const char *name, *kind;
long flags, owner = -1, group = -1;
- dir = opendir("/sys/class/net");
- if (!dir) {
- perror("opendir");
+ if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
+ return 0;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi)))
return -1;
+
+ switch (ifi->ifi_type) {
+ case ARPHRD_NONE:
+ case ARPHRD_ETHER:
+ break;
+ default:
+ return 0;
}
- while ((d = readdir(dir))) {
- if (d->d_name[0] == '.' &&
- (d->d_name[1] == 0 || d->d_name[1] == '.'))
- continue;
-
- if (read_prop(d->d_name, "tun_flags", &flags))
- continue;
-
- read_prop(d->d_name, "owner", &owner);
- read_prop(d->d_name, "group", &group);
-
- printf("%s:", d->d_name);
- print_flags(flags);
- if (owner != -1)
- printf(" user %ld", owner);
- if (group != -1)
- printf(" group %ld", group);
- printf("\n");
- if (show_details) {
- printf("\tAttached to processes:");
- show_processes(d->d_name);
- printf("\n");
- }
+
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
+
+ if (!tb[IFLA_IFNAME])
+ return 0;
+
+ if (!tb[IFLA_LINKINFO])
+ return 0;
+
+ parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+ if (!linkinfo[IFLA_INFO_KIND])
+ return 0;
+
+ kind = rta_getattr_str(linkinfo[IFLA_INFO_KIND]);
+ if (strcmp(kind, drv_name))
+ return 0;
+
+ name = rta_getattr_str(tb[IFLA_IFNAME]);
+
+ if (read_prop(name, "tun_flags", &flags))
+ return 0;
+ if (read_prop(name, "owner", &owner))
+ return 0;
+ if (read_prop(name, "group", &group))
+ return 0;
+
+ printf("%s:", name);
+ print_flags(flags);
+ if (owner != -1)
+ printf(" user %ld", owner);
+ if (group != -1)
+ printf(" group %ld", group);
+ fputc('\n', stdout);
+ if (show_details) {
+ printf("\tAttached to processes:");
+ show_processes(name);
+ fputc('\n', stdout);
}
- closedir(dir);
+
+ return 0;
+}
+
+static int do_show(int argc, char **argv)
+{
+ if (rtnl_wilddump_req_filter_fn(&rth, AF_UNSPEC, RTM_GETLINK,
+ tuntap_filter_req) < 0) {
+ perror("Cannot send dump request\n");
+ return -1;
+ }
+
+ if (rtnl_dump_filter(&rth, print_tuntap, NULL) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ return -1;
+ }
+
return 0;
}
--
1.7.10.4
prev parent reply other threads:[~2018-02-01 19:41 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-01 19:40 [RFC][PATCH iproute2-next 0/6] ip: Use netlink to walk through network device list Serhey Popovych
2018-02-01 19:40 ` [RFC][PATCH iproute2-next 1/6] ipaddress: Unify print_link_stats() and print_link_stats64() Serhey Popovych
2018-02-01 19:40 ` [RFC][PATCH iproute2-next 2/6] ip: Introduce get_rtnl_link_stats_rta() to get link statistics Serhey Popovych
2018-02-01 23:32 ` Stephen Hemminger
2018-02-01 19:40 ` [RFC][PATCH iproute2-next 3/6] tunnel: Split statistic getting and printing Serhey Popovych
2018-02-01 19:40 ` [RFC][PATCH iproute2-next 4/6] iptunnel/ip6tunnel: Code cleanups Serhey Popovych
2018-02-01 19:40 ` [RFC][PATCH iproute2-next 5/6] iptunnel/ip6tunnel: Use netlink to walk through tunnels list Serhey Popovych
2018-02-01 19:40 ` Serhey Popovych [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1517514058-23596-7-git-send-email-serhe.popovych@gmail.com \
--to=serhe.popovych@gmail.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).