* tun: add tun_flags, owner, group attributes in sysfs
@ 2009-05-04 10:32 David Woodhouse
2009-05-04 10:36 ` Michael Tokarev
` (4 more replies)
0 siblings, 5 replies; 23+ messages in thread
From: David Woodhouse @ 2009-05-04 10:32 UTC (permalink / raw)
To: netdev; +Cc: Mark McLoughlin
This patch adds three attribute files in /sys/class/net/$dev/ for tun
devices; allowing userspace to obtain the information which TUNGETIFF
offers, and more, but without having to attach to the device in question
(which may not be possible if it's in use).
It also fixes a bug which has been present in the TUNGETIFF ioctl since
its inception, where it would never set IFF_TUN or IFF_TAP according to
the device type. (Look carefully at the code which I remove from
tun_get_iff() and how the new tun_flags() helper is subtly different).
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---
I don't have to explicitly remove the files, do I? They go away
naturally when the device is unregistered?
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 94622e5..4cda69b 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -865,6 +865,52 @@ static struct proto tun_proto = {
.obj_size = sizeof(struct tun_sock),
};
+static int tun_flags(struct tun_struct *tun)
+{
+ int flags = 0;
+
+ if (tun->flags & TUN_TUN_DEV)
+ flags |= IFF_TUN;
+ else
+ flags |= IFF_TAP;
+
+ if (tun->flags & TUN_NO_PI)
+ flags |= IFF_NO_PI;
+
+ if (tun->flags & TUN_ONE_QUEUE)
+ flags |= IFF_ONE_QUEUE;
+
+ if (tun->flags & TUN_VNET_HDR)
+ flags |= IFF_VNET_HDR;
+
+ return flags;
+}
+
+static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tun_struct *tun = netdev_priv(to_net_dev(dev));
+ return sprintf(buf, "0x%x\n", tun_flags(tun));
+}
+
+static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tun_struct *tun = netdev_priv(to_net_dev(dev));
+ return sprintf(buf, "%d\n", tun->owner);
+}
+
+static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tun_struct *tun = netdev_priv(to_net_dev(dev));
+ return sprintf(buf, "%d\n", tun->group);
+}
+
+static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL);
+static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL);
+static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
+
static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
{
struct sock *sk;
@@ -950,6 +996,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
if (err < 0)
goto err_free_sk;
+ if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
+ device_create_file(&tun->dev->dev, &dev_attr_owner) ||
+ device_create_file(&tun->dev->dev, &dev_attr_group))
+ printk(KERN_ERR "Failed to create tun sysfs files\n");
+
sk->sk_destruct = tun_sock_destruct;
err = tun_attach(tun, file);
@@ -1002,21 +1053,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
strcpy(ifr->ifr_name, tun->dev->name);
- ifr->ifr_flags = 0;
-
- if (ifr->ifr_flags & TUN_TUN_DEV)
- ifr->ifr_flags |= IFF_TUN;
- else
- ifr->ifr_flags |= IFF_TAP;
-
- if (tun->flags & TUN_NO_PI)
- ifr->ifr_flags |= IFF_NO_PI;
-
- if (tun->flags & TUN_ONE_QUEUE)
- ifr->ifr_flags |= IFF_ONE_QUEUE;
-
- if (tun->flags & TUN_VNET_HDR)
- ifr->ifr_flags |= IFF_VNET_HDR;
+ ifr->ifr_flags = tun_flags(tun);
tun_put(tun);
return 0;
--
David Woodhouse Open Source Technology Centre
David.Woodhouse@intel.com Intel Corporation
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-04 10:32 tun: add tun_flags, owner, group attributes in sysfs David Woodhouse @ 2009-05-04 10:36 ` Michael Tokarev 2009-05-05 22:18 ` David Woodhouse 2009-05-04 10:42 ` [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices David Woodhouse ` (3 subsequent siblings) 4 siblings, 1 reply; 23+ messages in thread From: Michael Tokarev @ 2009-05-04 10:36 UTC (permalink / raw) To: David Woodhouse; +Cc: netdev, Mark McLoughlin David Woodhouse wrote: > This patch adds three attribute files in /sys/class/net/$dev/ for tun > devices; allowing userspace to obtain the information which TUNGETIFF > offers, and more, but without having to attach to the device in question > (which may not be possible if it's in use). > [] > +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); > +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); > +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); Is there any reason why those files are not writable? I understand flags one, sorta (but it is still useful to be able to change some flags, like persistent, while it's running), but for owner/group - it's just an integer that's used to check permissions for ioctl, and can be set in sysfs just fine. I think anyway. /mjt ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-04 10:36 ` Michael Tokarev @ 2009-05-05 22:18 ` David Woodhouse 0 siblings, 0 replies; 23+ messages in thread From: David Woodhouse @ 2009-05-05 22:18 UTC (permalink / raw) To: Michael Tokarev; +Cc: netdev, Mark McLoughlin On Mon, 2009-05-04 at 14:36 +0400, Michael Tokarev wrote: > David Woodhouse wrote: > > This patch adds three attribute files in /sys/class/net/$dev/ for tun > > devices; allowing userspace to obtain the information which TUNGETIFF > > offers, and more, but without having to attach to the device in question > > (which may not be possible if it's in use). > > > [] > > +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); > > +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); > > +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); > > Is there any reason why those files are not writable? > > I understand flags one, sorta (but it is still useful to > be able to change some flags, like persistent, while it's > running), but for owner/group - it's just an integer that's > used to check permissions for ioctl, and can be set in sysfs > just fine. I think anyway. I did think about it, but didn't see the point. There's little benefit in being able to write owner/group through sysfs, and it's non-trivial to get the permissions right. You can currently change owner/group if you can attach to the device... and you can attach to the device if you're _already_ the appropriate uid/gid, or if you have CAP_NET_ADMIN. We can't make opens for write fail, as far as I'm aware -- the best we could do is to reproduce the permissions check in the sysfs set function, and return -EPERM to the _write_, which doesn't really fill me with joy. Being able to mark a device as non-persistent through sysfs while it's open would be cute, I suppose -- but not cute enough that it's worth having to deal with the case of marking it non-persistent that way while it's _not_ open, which means it needs to disappear as soon as you write the flags variable... On the whole, it seemed better just to have them read-only. That's all we really need, after all. -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-04 10:32 tun: add tun_flags, owner, group attributes in sysfs David Woodhouse 2009-05-04 10:36 ` Michael Tokarev @ 2009-05-04 10:42 ` David Woodhouse 2009-05-04 14:38 ` Stephen Hemminger 2009-05-28 4:58 ` Stephen Hemminger 2009-05-04 14:47 ` tun: add tun_flags, owner, group attributes in sysfs Stephen Hemminger ` (2 subsequent siblings) 4 siblings, 2 replies; 23+ messages in thread From: David Woodhouse @ 2009-05-04 10:42 UTC (permalink / raw) To: stephen.hemminger; +Cc: netdev This patch provides support for 'ip tuntap', allowing creation and deletion of persistent tun/tap devices. The support for _listing_ devices relies on the patch I just sent to netdev (<1241433136.6126.70.camel@macbook.infradead.org>), although creation and deletion work without that patch. diff --git a/ip/Makefile b/ip/Makefile index 98ba876..e868f3e 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -1,6 +1,6 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \ rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \ - ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \ + ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \ ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ iplink_vlan.o link_veth.o link_gre.o diff --git a/ip/ip.c b/ip/ip.c index 2bd54b2..d846a76 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -47,7 +47,7 @@ static void usage(void) "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" " ip [ -force ] -batch filename\n" "where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n" -" tunnel | maddr | mroute | monitor | xfrm }\n" +" tunnel | tuntap | maddr | mroute | monitor | xfrm }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -f[amily] { inet | inet6 | ipx | dnet | link } |\n" " -o[neline] | -t[imestamp] | -b[atch] [filename] }\n"); @@ -75,6 +75,8 @@ static const struct cmd { { "link", do_iplink }, { "tunnel", do_iptunnel }, { "tunl", do_iptunnel }, + { "tuntap", do_iptuntap }, + { "tap", do_iptuntap }, { "monitor", do_ipmonitor }, { "xfrm", do_xfrm }, { "mroute", do_multiroute }, diff --git a/ip/ip_common.h b/ip/ip_common.h index 273065f..c857667 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -32,6 +32,7 @@ extern int do_ipneigh(int argc, char **argv); extern int do_ipntable(int argc, char **argv); extern int do_iptunnel(int argc, char **argv); extern int do_ip6tunnel(int argc, char **argv); +extern int do_iptuntap(int argc, char **argv); extern int do_iplink(int argc, char **argv); extern int do_ipmonitor(int argc, char **argv); extern int do_multiaddr(int argc, char **argv); diff --git a/ip/iptuntap.c b/ip/iptuntap.c new file mode 100644 index 0000000..b480296 --- /dev/null +++ b/ip/iptuntap.c @@ -0,0 +1,322 @@ +/* + * iptunnel.c "ip tuntap" + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: David Woodhouse <David.Woodhouse@intel.com> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <pwd.h> +#include <grp.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +#define TUNDEV "/dev/net/tun" + +static void usage(void) __attribute__((noreturn)); + +static void usage(void) +{ + fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n"); + fprintf(stderr, " [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"); + fprintf(stderr, " [ one_queue ] [ no_pi ] [ vnet_hdr ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Where: USER := { STRING | NUMBER }\n"); + fprintf(stderr, " GROUP := { STRING | NUMBER }\n"); + exit(-1); +} + +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) +{ + int fd = open(TUNDEV, O_RDWR); + int ret = -1; + +#ifndef IFF_TUN_EXCL +#define IFF_TUN_EXCL 0x8000 +#endif + ifr->ifr_flags |= IFF_TUN_EXCL; + + if (fd < 0) { + perror("open"); + return -1; + } + if (ioctl(fd, TUNSETIFF, ifr)) { + perror("ioctl(TUNSETIFF)"); + goto out; + } + if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) { + perror("ioctl(TUNSETOWNER)"); + goto out; + } + if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) { + perror("ioctl(TUNSETGROUP)"); + goto out; + } + if (ioctl(fd, TUNSETPERSIST, 1)) { + perror("ioctl(TUNSETPERSIST)"); + goto out; + } + ret = 0; + out: + close(fd); + return ret; +} + +static int tap_del_ioctl(struct ifreq *ifr) +{ + int fd = open(TUNDEV, O_RDWR); + int ret = -1; + + if (fd < 0) { + perror("open"); + return -1; + } + if (ioctl(fd, TUNSETIFF, ifr)) { + perror("ioctl(TUNSETIFF)"); + goto out; + } + if (ioctl(fd, TUNSETPERSIST, 0)) { + perror("ioctl(TUNSETPERSIST)"); + goto out; + } + ret = 0; + out: + close(fd); + return ret; + +} +static int parse_args(int argc, char **argv, struct ifreq *ifr, uid_t *uid, gid_t *gid) +{ + int count = 0; + + memset(ifr, 0, sizeof(*ifr)); + + ifr->ifr_flags |= IFF_NO_PI; + + while (argc > 0) { + if (strcmp(*argv, "mode") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "tun") == 0) { + if (ifr->ifr_flags & IFF_TAP) { + fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); + exit(-1); + } + ifr->ifr_flags |= IFF_TUN; + } else if (strcmp(*argv, "tap") == 0) { + if (ifr->ifr_flags & IFF_TUN) { + fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); + exit(-1); + } + ifr->ifr_flags |= IFF_TAP; + } else { + fprintf(stderr,"Cannot guess tunnel mode.\n"); + exit(-1); + } + } else if (uid && strcmp(*argv, "user") == 0) { + char *end; + unsigned long user; + + NEXT_ARG(); + if (**argv && ((user = strtol(*argv, &end, 10)), !*end)) + *uid = user; + else { + struct passwd *pw = getpwnam(*argv); + if (!pw) { + fprintf(stderr, "invalid user \"%s\"\n", *argv); + exit(-1); + } + *uid = pw->pw_uid; + } + } else if (gid && strcmp(*argv, "group") == 0) { + char *end; + unsigned long group; + + NEXT_ARG(); + + if (**argv && ((group = strtol(*argv, &end, 10)), !*end)) + *gid = group; + else { + struct group *gr = getgrnam(*argv); + if (!gr) { + fprintf(stderr, "invalid group \"%s\"\n", *argv); + exit(-1); + } + *gid = gr->gr_gid; + } + } else if (strcmp(*argv, "pi") == 0) { + ifr->ifr_flags &= ~IFF_NO_PI; + } else if (strcmp(*argv, "one_queue") == 0) { + ifr->ifr_flags |= IFF_ONE_QUEUE; + } else if (strcmp(*argv, "vnet_hdr") == 0) { + ifr->ifr_flags |= IFF_VNET_HDR; + } else if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1); + } else { + if (strcmp(*argv, "name") == 0) { + NEXT_ARG(); + } else if (matches(*argv, "help") == 0) + usage(); + if (ifr->ifr_name[0]) + duparg2("name", *argv); + strncpy(ifr->ifr_name, *argv, IFNAMSIZ); + } + count++; + argc--; argv++; + } + + return 0; +} + + +static int do_add(int argc, char **argv) +{ + struct ifreq ifr; + uid_t uid = -1; + gid_t gid = -1; + + if (parse_args(argc, argv, &ifr, &uid, &gid) < 0) + return -1; + + if (!(ifr.ifr_flags & TUN_TYPE_MASK)) { + fprintf(stderr, "You failed to specify a tunnel mode\n"); + return -1; + } + return tap_add_ioctl(&ifr, uid, gid); +} + +static int do_del(int argc, char **argv) +{ + struct ifreq ifr; + + if (parse_args(argc, argv, &ifr, NULL, NULL) < 0) + return -1; + + return tap_del_ioctl(&ifr); +} + +static int read_prop(char *dev, char *prop, long *value) +{ + char fname[IFNAMSIZ+25], buf[80], *endp; + ssize_t len; + int fd; + long result; + + sprintf(fname, "/sys/class/net/%s/%s", dev, prop); + fd = open(fname, O_RDONLY); + if (fd < 0) { + if (strcmp(prop, "tun_flags")) + fprintf(stderr, "open %s: %s\n", fname, strerror(errno)); + return -1; + } + len = read(fd, buf, sizeof(buf)-1); + close(fd); + if (len < 0) { + fprintf(stderr, "read %s: %s", fname, strerror(errno)); + return -1; + } + + buf[len] = 0; + result = strtol(buf, &endp, 0); + if (*endp != '\n') { + fprintf(stderr, "Failed to parse %s\n", fname); + return -1; + } + *value = result; + return 0; +} + +static void print_flags(long flags) +{ + if (flags & IFF_TUN) + printf(" tun"); + + if (flags & IFF_TAP) + printf(" tap"); + + if (!(flags & IFF_NO_PI)) + printf(" pi"); + + if (flags & IFF_ONE_QUEUE) + printf(" one_queue"); + + if (flags & IFF_VNET_HDR) + printf(" vnet_hdr"); + + flags &= ~(IFF_TUN|IFF_TAP|IFF_NO_PI|IFF_ONE_QUEUE|IFF_VNET_HDR); + if (flags) + printf(" UNKNOWN_FLAGS:%x", flags); +} + +static int do_show(int argc, char **argv) +{ + DIR *dir; + struct dirent *d; + long flags, owner = -1, group = -1; + int i; + + dir = opendir("/sys/class/net"); + if (!dir) { + perror("opendir"); + return -1; + } + 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"); + } + return 0; +} + +int do_iptuntap(int argc, char **argv) +{ + if (argc > 0) { + if (matches(*argv, "add") == 0) + return do_add(argc-1, argv+1); + if (matches(*argv, "del") == 0) + return do_del(argc-1, argv+1); + if (matches(*argv, "show") == 0 || + matches(*argv, "lst") == 0 || + matches(*argv, "list") == 0) + return do_show(argc-1, argv+1); + if (matches(*argv, "help") == 0) + usage(); + } else + return do_show(0, NULL); + + fprintf(stderr, "Command \"%s\" is unknown, try \"ip tuntap help\".\n", *argv); + exit(-1); +} -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-04 10:42 ` [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices David Woodhouse @ 2009-05-04 14:38 ` Stephen Hemminger 2009-05-04 14:49 ` David Woodhouse 2009-05-28 4:58 ` Stephen Hemminger 1 sibling, 1 reply; 23+ messages in thread From: Stephen Hemminger @ 2009-05-04 14:38 UTC (permalink / raw) To: David Woodhouse; +Cc: stephen.hemminger, netdev On Mon, 04 May 2009 11:42:58 +0100 David Woodhouse <dwmw2@infradead.org> wrote: > This patch provides support for 'ip tuntap', allowing creation and > deletion of persistent tun/tap devices. > > The support for _listing_ devices relies on the patch I just sent to > netdev (<1241433136.6126.70.camel@macbook.infradead.org>), although > creation and deletion work without that patch. > > diff --git a/ip/Makefile b/ip/Makefile > index 98ba876..e868f3e 100644 > --- a/ip/Makefile > +++ b/ip/Makefile > @@ -1,6 +1,6 @@ > IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \ > rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \ > - ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \ > + ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \ > ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ > iplink_vlan.o link_veth.o link_gre.o > > diff --git a/ip/ip.c b/ip/ip.c > index 2bd54b2..d846a76 100644 > --- a/ip/ip.c > +++ b/ip/ip.c > @@ -47,7 +47,7 @@ static void usage(void) > "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" > " ip [ -force ] -batch filename\n" > "where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n" > -" tunnel | maddr | mroute | monitor | xfrm }\n" > +" tunnel | tuntap | maddr | mroute | monitor | xfrm }\n" > " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" > " -f[amily] { inet | inet6 | ipx | dnet | link } |\n" > " -o[neline] | -t[imestamp] | -b[atch] [filename] }\n"); > @@ -75,6 +75,8 @@ static const struct cmd { > { "link", do_iplink }, > { "tunnel", do_iptunnel }, > { "tunl", do_iptunnel }, > + { "tuntap", do_iptuntap }, > + { "tap", do_iptuntap }, > { "monitor", do_ipmonitor }, > { "xfrm", do_xfrm }, > { "mroute", do_multiroute }, > diff --git a/ip/ip_common.h b/ip/ip_common.h > index 273065f..c857667 100644 > --- a/ip/ip_common.h > +++ b/ip/ip_common.h > @@ -32,6 +32,7 @@ extern int do_ipneigh(int argc, char **argv); > extern int do_ipntable(int argc, char **argv); > extern int do_iptunnel(int argc, char **argv); > extern int do_ip6tunnel(int argc, char **argv); > +extern int do_iptuntap(int argc, char **argv); > extern int do_iplink(int argc, char **argv); > extern int do_ipmonitor(int argc, char **argv); > extern int do_multiaddr(int argc, char **argv); > diff --git a/ip/iptuntap.c b/ip/iptuntap.c > new file mode 100644 > index 0000000..b480296 > --- /dev/null > +++ b/ip/iptuntap.c > @@ -0,0 +1,322 @@ > +/* > + * iptunnel.c "ip tuntap" > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + * > + * Authors: David Woodhouse <David.Woodhouse@intel.com> > + * > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/socket.h> > +#include <arpa/inet.h> > +#include <sys/ioctl.h> > +#include <linux/if.h> > +#include <linux/if_tun.h> > +#include <pwd.h> > +#include <grp.h> > +#include <fcntl.h> > +#include <dirent.h> > +#include <errno.h> > + > +#include "rt_names.h" > +#include "utils.h" > +#include "ip_common.h" > + > +#define TUNDEV "/dev/net/tun" > + > +static void usage(void) __attribute__((noreturn)); > + > +static void usage(void) > +{ > + fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n"); > + fprintf(stderr, " [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"); > + fprintf(stderr, " [ one_queue ] [ no_pi ] [ vnet_hdr ]\n"); > + fprintf(stderr, "\n"); > + fprintf(stderr, "Where: USER := { STRING | NUMBER }\n"); > + fprintf(stderr, " GROUP := { STRING | NUMBER }\n"); > + exit(-1); > +} > + > +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) > +{ > + int fd = open(TUNDEV, O_RDWR); > + int ret = -1; > + > +#ifndef IFF_TUN_EXCL > +#define IFF_TUN_EXCL 0x8000 > +#endif > + ifr->ifr_flags |= IFF_TUN_EXCL; > + > + if (fd < 0) { > + perror("open"); > + return -1; > + } > + if (ioctl(fd, TUNSETIFF, ifr)) { > + perror("ioctl(TUNSETIFF)"); > + goto out; > + } > + if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) { > + perror("ioctl(TUNSETOWNER)"); > + goto out; > + } > + if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) { > + perror("ioctl(TUNSETGROUP)"); > + goto out; > + } > + if (ioctl(fd, TUNSETPERSIST, 1)) { > + perror("ioctl(TUNSETPERSIST)"); > + goto out; > + } > + ret = 0; > + out: > + close(fd); > + return ret; > +} > + I would rather provide a netlink for managing TUNTAP interfaces and reorganize under ip link?? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-04 14:38 ` Stephen Hemminger @ 2009-05-04 14:49 ` David Woodhouse 2009-05-27 16:32 ` David Woodhouse 0 siblings, 1 reply; 23+ messages in thread From: David Woodhouse @ 2009-05-04 14:49 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On Mon, 2009-05-04 at 07:38 -0700, Stephen Hemminger wrote: > I would rather provide a netlink for managing TUNTAP interfaces I'm not sure that makes a lot of sense. We'd be adding a new, duplicate user API solely for the benefit of iproute2; it's not as if we'd ever be able to get rid of the existing interface that everyone uses. Unless you want to ditch the /dev/net/tun chardev completely and do _everything_ over netlink, maybe... but that doesn't seem particularly worthwhile either. > and reorganize under ip link?? It seemed more intuitive to model it after 'ip tunnel'. How would you want it to look? -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-04 14:49 ` David Woodhouse @ 2009-05-27 16:32 ` David Woodhouse 2009-05-27 16:38 ` Stephen Hemminger 0 siblings, 1 reply; 23+ messages in thread From: David Woodhouse @ 2009-05-27 16:32 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On Mon, 2009-05-04 at 15:49 +0100, David Woodhouse wrote: > On Mon, 2009-05-04 at 07:38 -0700, Stephen Hemminger wrote: > > I would rather provide a netlink for managing TUNTAP interfaces > > I'm not sure that makes a lot of sense. We'd be adding a new, duplicate > user API solely for the benefit of iproute2; it's not as if we'd ever be > able to get rid of the existing interface that everyone uses. > > Unless you want to ditch the /dev/net/tun chardev completely and do > _everything_ over netlink, maybe... but that doesn't seem particularly > worthwhile either. > > > and reorganize under ip link?? > > It seemed more intuitive to model it after 'ip tunnel'. How would you > want it to look? Ping? -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-27 16:32 ` David Woodhouse @ 2009-05-27 16:38 ` Stephen Hemminger 2009-05-27 16:49 ` David Woodhouse 0 siblings, 1 reply; 23+ messages in thread From: Stephen Hemminger @ 2009-05-27 16:38 UTC (permalink / raw) To: David Woodhouse; +Cc: netdev On Wed, 27 May 2009 17:32:17 +0100 David Woodhouse <dwmw2@infradead.org> wrote: > On Mon, 2009-05-04 at 15:49 +0100, David Woodhouse wrote: > > On Mon, 2009-05-04 at 07:38 -0700, Stephen Hemminger wrote: > > > I would rather provide a netlink for managing TUNTAP interfaces > > > > I'm not sure that makes a lot of sense. We'd be adding a new, duplicate > > user API solely for the benefit of iproute2; it's not as if we'd ever be > > able to get rid of the existing interface that everyone uses. > > > > Unless you want to ditch the /dev/net/tun chardev completely and do > > _everything_ over netlink, maybe... but that doesn't seem particularly > > worthwhile either. > > > > > and reorganize under ip link?? > > > > It seemed more intuitive to model it after 'ip tunnel'. How would you > > want it to look? > > Ping? > Almost all of iproute2 is based on netlink, I don't want to add non netlink interfaces. -- ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-27 16:38 ` Stephen Hemminger @ 2009-05-27 16:49 ` David Woodhouse 2009-05-27 17:06 ` Stephen Hemminger 2009-05-27 20:43 ` David Miller 0 siblings, 2 replies; 23+ messages in thread From: David Woodhouse @ 2009-05-27 16:49 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On Wed, 2009-05-27 at 09:38 -0700, Stephen Hemminger wrote: > On Wed, 27 May 2009 17:32:17 +0100 > David Woodhouse <dwmw2@infradead.org> wrote: > > > On Mon, 2009-05-04 at 15:49 +0100, David Woodhouse wrote: > > > On Mon, 2009-05-04 at 07:38 -0700, Stephen Hemminger wrote: > > > > I would rather provide a netlink for managing TUNTAP interfaces > > > > > > I'm not sure that makes a lot of sense. We'd be adding a new, duplicate > > > user API solely for the benefit of iproute2; it's not as if we'd ever be > > > able to get rid of the existing interface that everyone uses. > > > > > > Unless you want to ditch the /dev/net/tun chardev completely and do > > > _everything_ over netlink, maybe... but that doesn't seem particularly > > > worthwhile either. > > > > > > > and reorganize under ip link?? > > > > > > It seemed more intuitive to model it after 'ip tunnel'. How would you > > > want it to look? > > > > Ping? > > > > Almost all of iproute2 is based on netlink, I don't want to add non netlink > interfaces. So you want to add a new interface to the kernel which duplicates the one we've had for years, then make userspace which will only work with newer kernels? -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-27 16:49 ` David Woodhouse @ 2009-05-27 17:06 ` Stephen Hemminger 2009-05-27 20:44 ` David Miller 2009-05-27 20:43 ` David Miller 1 sibling, 1 reply; 23+ messages in thread From: Stephen Hemminger @ 2009-05-27 17:06 UTC (permalink / raw) To: David Woodhouse; +Cc: netdev On Wed, 27 May 2009 17:49:32 +0100 David Woodhouse <dwmw2@infradead.org> wrote: > On Wed, 2009-05-27 at 09:38 -0700, Stephen Hemminger wrote: > > On Wed, 27 May 2009 17:32:17 +0100 > > David Woodhouse <dwmw2@infradead.org> wrote: > > > > > On Mon, 2009-05-04 at 15:49 +0100, David Woodhouse wrote: > > > > On Mon, 2009-05-04 at 07:38 -0700, Stephen Hemminger wrote: > > > > > I would rather provide a netlink for managing TUNTAP interfaces > > > > > > > > I'm not sure that makes a lot of sense. We'd be adding a new, duplicate > > > > user API solely for the benefit of iproute2; it's not as if we'd ever be > > > > able to get rid of the existing interface that everyone uses. > > > > > > > > Unless you want to ditch the /dev/net/tun chardev completely and do > > > > _everything_ over netlink, maybe... but that doesn't seem particularly > > > > worthwhile either. > > > > > > > > > and reorganize under ip link?? > > > > > > > > It seemed more intuitive to model it after 'ip tunnel'. How would you > > > > want it to look? > > > > > > Ping? > > > > > > > Almost all of iproute2 is based on netlink, I don't want to add non netlink > > interfaces. > > So you want to add a new interface to the kernel which duplicates the > one we've had for years, then make userspace which will only work with > newer kernels? Well if the kernel interface existed for years, there were obviously other tools using it. Why do you have to cram that into iproute2? -- ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-27 17:06 ` Stephen Hemminger @ 2009-05-27 20:44 ` David Miller 0 siblings, 0 replies; 23+ messages in thread From: David Miller @ 2009-05-27 20:44 UTC (permalink / raw) To: shemminger; +Cc: dwmw2, netdev From: Stephen Hemminger <shemminger@vyatta.com> Date: Wed, 27 May 2009 10:06:47 -0700 > Well if the kernel interface existed for years, there were obviously other > tools using it. Why do you have to cram that into iproute2? Because iproute2 is what we want everyone to use perhaps?!?!?!? Stephen, STOP THIS PASSIVE AGGRESSIVE CRAP. It's not becoming, and it's just delaying making iproute2 more useful by supporting tuntap devices properly. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-27 16:49 ` David Woodhouse 2009-05-27 17:06 ` Stephen Hemminger @ 2009-05-27 20:43 ` David Miller 1 sibling, 0 replies; 23+ messages in thread From: David Miller @ 2009-05-27 20:43 UTC (permalink / raw) To: dwmw2; +Cc: shemminger, netdev From: David Woodhouse <dwmw2@infradead.org> Date: Wed, 27 May 2009 17:49:32 +0100 > On Wed, 2009-05-27 at 09:38 -0700, Stephen Hemminger wrote: >> Almost all of iproute2 is based on netlink, I don't want to add non netlink >> interfaces. > > So you want to add a new interface to the kernel which duplicates the > one we've had for years, then make userspace which will only work with > newer kernels? I agree, Stephen just put in the ioctl() or whatever based support for TUN devices. We've done stuff like this before in iproute2 so your arguments against this are hogwash. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-04 10:42 ` [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices David Woodhouse 2009-05-04 14:38 ` Stephen Hemminger @ 2009-05-28 4:58 ` Stephen Hemminger 2009-05-28 8:12 ` David Woodhouse 1 sibling, 1 reply; 23+ messages in thread From: Stephen Hemminger @ 2009-05-28 4:58 UTC (permalink / raw) To: David Woodhouse; +Cc: stephen.hemminger, netdev On Mon, 04 May 2009 11:42:58 +0100 David Woodhouse <dwmw2@infradead.org> wrote: > This patch provides support for 'ip tuntap', allowing creation and > deletion of persistent tun/tap devices. > > The support for _listing_ devices relies on the patch I just sent to > netdev (<1241433136.6126.70.camel@macbook.infradead.org>), although > creation and deletion work without that patch. > > diff --git a/ip/Makefile b/ip/Makefile > index 98ba876..e868f3e 100644 > --- a/ip/Makefile > +++ b/ip/Makefile > @@ -1,6 +1,6 @@ > IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \ > rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \ > - ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \ > + ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \ > ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ > iplink_vlan.o link_veth.o link_gre.o > > diff --git a/ip/ip.c b/ip/ip.c > index 2bd54b2..d846a76 100644 > --- a/ip/ip.c > +++ b/ip/ip.c > @@ -47,7 +47,7 @@ static void usage(void) > "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" > " ip [ -force ] -batch filename\n" > "where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n" > -" tunnel | maddr | mroute | monitor | xfrm }\n" > +" tunnel | tuntap | maddr | mroute | monitor | xfrm }\n" > " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" > " -f[amily] { inet | inet6 | ipx | dnet | link } |\n" > " -o[neline] | -t[imestamp] | -b[atch] [filename] }\n"); > @@ -75,6 +75,8 @@ static const struct cmd { > { "link", do_iplink }, > { "tunnel", do_iptunnel }, > { "tunl", do_iptunnel }, > + { "tuntap", do_iptuntap }, > + { "tap", do_iptuntap }, > { "monitor", do_ipmonitor }, > { "xfrm", do_xfrm }, > { "mroute", do_multiroute }, > diff --git a/ip/ip_common.h b/ip/ip_common.h > index 273065f..c857667 100644 > --- a/ip/ip_common.h > +++ b/ip/ip_common.h > @@ -32,6 +32,7 @@ extern int do_ipneigh(int argc, char **argv); > extern int do_ipntable(int argc, char **argv); > extern int do_iptunnel(int argc, char **argv); > extern int do_ip6tunnel(int argc, char **argv); > +extern int do_iptuntap(int argc, char **argv); > extern int do_iplink(int argc, char **argv); > extern int do_ipmonitor(int argc, char **argv); > extern int do_multiaddr(int argc, char **argv); > diff --git a/ip/iptuntap.c b/ip/iptuntap.c > new file mode 100644 > index 0000000..b480296 > --- /dev/null > +++ b/ip/iptuntap.c > @@ -0,0 +1,322 @@ > +/* > + * iptunnel.c "ip tuntap" > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + * > + * Authors: David Woodhouse <David.Woodhouse@intel.com> > + * > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/socket.h> > +#include <arpa/inet.h> > +#include <sys/ioctl.h> > +#include <linux/if.h> > +#include <linux/if_tun.h> > +#include <pwd.h> > +#include <grp.h> > +#include <fcntl.h> > +#include <dirent.h> > +#include <errno.h> > + > +#include "rt_names.h" > +#include "utils.h" > +#include "ip_common.h" > + > +#define TUNDEV "/dev/net/tun" I know this is historical legacy, but how does this play with network namespaces? > + > +static void usage(void) __attribute__((noreturn)); > + > +static void usage(void) > +{ > + fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n"); > + fprintf(stderr, " [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"); > + fprintf(stderr, " [ one_queue ] [ no_pi ] [ vnet_hdr ]\n"); > + fprintf(stderr, "\n"); > + fprintf(stderr, "Where: USER := { STRING | NUMBER }\n"); > + fprintf(stderr, " GROUP := { STRING | NUMBER }\n"); > + exit(-1); > +} > + > +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) > +{ > + int fd = open(TUNDEV, O_RDWR); > + int ret = -1; > + > +#ifndef IFF_TUN_EXCL > +#define IFF_TUN_EXCL 0x8000 > +#endif This shouldn't be here. It should be defined in include/linux/if_tun.h in kernel source and then a kernel sanitized version of if_tun.h should be put in iproute2 source for backwards compatibility. But why bother it doesn't seem to be defined or used by current kernel?? > + ifr->ifr_flags |= IFF_TUN_EXCL; Would prefer open() next to the test. > + if (fd < 0) { > + perror("open"); > + return -1; > + } > + if (ioctl(fd, TUNSETIFF, ifr)) { > + perror("ioctl(TUNSETIFF)"); > + goto out; > + } > + if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) { > + perror("ioctl(TUNSETOWNER)"); > + goto out; > + } > + if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) { > + perror("ioctl(TUNSETGROUP)"); > + goto out; > + } > + if (ioctl(fd, TUNSETPERSIST, 1)) { > + perror("ioctl(TUNSETPERSIST)"); > + goto out; > + } > + ret = 0; > + out: > + close(fd); > + return ret; > +} > + > +static int tap_del_ioctl(struct ifreq *ifr) > +{ > + int fd = open(TUNDEV, O_RDWR); > + int ret = -1; > + > + if (fd < 0) { > + perror("open"); > + return -1; > + } > + if (ioctl(fd, TUNSETIFF, ifr)) { > + perror("ioctl(TUNSETIFF)"); > + goto out; > + } > + if (ioctl(fd, TUNSETPERSIST, 0)) { > + perror("ioctl(TUNSETPERSIST)"); > + goto out; > + } > + ret = 0; > + out: > + close(fd); > + return ret; > + > +} > +static int parse_args(int argc, char **argv, struct ifreq *ifr, uid_t *uid, gid_t *gid) > +{ > + int count = 0; > + > + memset(ifr, 0, sizeof(*ifr)); > + > + ifr->ifr_flags |= IFF_NO_PI; > + > + while (argc > 0) { > + if (strcmp(*argv, "mode") == 0) { The argument parsing in ip commands uses matches() rather than strcmp to allow for partial completion. > + NEXT_ARG(); > + if (strcmp(*argv, "tun") == 0) { > + if (ifr->ifr_flags & IFF_TAP) { > + fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); > + exit(-1); > + } > + ifr->ifr_flags |= IFF_TUN; > + } else if (strcmp(*argv, "tap") == 0) { > + if (ifr->ifr_flags & IFF_TUN) { > + fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); > + exit(-1); > + } > + ifr->ifr_flags |= IFF_TAP; > + } else { > + fprintf(stderr,"Cannot guess tunnel mode.\n"); > + exit(-1); > + } > + } else if (uid && strcmp(*argv, "user") == 0) { > + char *end; > + unsigned long user; > + > + NEXT_ARG(); > + if (**argv && ((user = strtol(*argv, &end, 10)), !*end)) > + *uid = user; > + else { > + struct passwd *pw = getpwnam(*argv); > + if (!pw) { > + fprintf(stderr, "invalid user \"%s\"\n", *argv); > + exit(-1); > + } > + *uid = pw->pw_uid; > + } > + } else if (gid && strcmp(*argv, "group") == 0) { > + char *end; > + unsigned long group; > + > + NEXT_ARG(); > + > + if (**argv && ((group = strtol(*argv, &end, 10)), !*end)) > + *gid = group; > + else { > + struct group *gr = getgrnam(*argv); > + if (!gr) { > + fprintf(stderr, "invalid group \"%s\"\n", *argv); > + exit(-1); > + } > + *gid = gr->gr_gid; > + } > + } else if (strcmp(*argv, "pi") == 0) { > + ifr->ifr_flags &= ~IFF_NO_PI; > + } else if (strcmp(*argv, "one_queue") == 0) { > + ifr->ifr_flags |= IFF_ONE_QUEUE; > + } else if (strcmp(*argv, "vnet_hdr") == 0) { > + ifr->ifr_flags |= IFF_VNET_HDR; > + } else if (strcmp(*argv, "dev") == 0) { > + NEXT_ARG(); > + strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1); > + } else { > + if (strcmp(*argv, "name") == 0) { > + NEXT_ARG(); > + } else if (matches(*argv, "help") == 0) > + usage(); > + if (ifr->ifr_name[0]) > + duparg2("name", *argv); > + strncpy(ifr->ifr_name, *argv, IFNAMSIZ); > + } > + count++; > + argc--; argv++; > + } > + > + return 0; > +} > + > + > +static int do_add(int argc, char **argv) > +{ > + struct ifreq ifr; > + uid_t uid = -1; > + gid_t gid = -1; > + > + if (parse_args(argc, argv, &ifr, &uid, &gid) < 0) > + return -1; > + > + if (!(ifr.ifr_flags & TUN_TYPE_MASK)) { > + fprintf(stderr, "You failed to specify a tunnel mode\n"); > + return -1; > + } > + return tap_add_ioctl(&ifr, uid, gid); > +} > + > +static int do_del(int argc, char **argv) > +{ > + struct ifreq ifr; > + > + if (parse_args(argc, argv, &ifr, NULL, NULL) < 0) > + return -1; > + > + return tap_del_ioctl(&ifr); > +} > + > +static int read_prop(char *dev, char *prop, long *value) > +{ > + char fname[IFNAMSIZ+25], buf[80], *endp; > + ssize_t len; > + int fd; > + long result; > + > + sprintf(fname, "/sys/class/net/%s/%s", dev, prop); > + fd = open(fname, O_RDONLY); > + if (fd < 0) { > + if (strcmp(prop, "tun_flags")) > + fprintf(stderr, "open %s: %s\n", fname, strerror(errno)); > + return -1; > + } > + len = read(fd, buf, sizeof(buf)-1); > + close(fd); > + if (len < 0) { > + fprintf(stderr, "read %s: %s", fname, strerror(errno)); > + return -1; > + } > + > + buf[len] = 0; > + result = strtol(buf, &endp, 0); > + if (*endp != '\n') { > + fprintf(stderr, "Failed to parse %s\n", fname); > + return -1; > + } > + *value = result; > + return 0; > +} > + > +static void print_flags(long flags) > +{ > + if (flags & IFF_TUN) > + printf(" tun"); > + > + if (flags & IFF_TAP) > + printf(" tap"); > + > + if (!(flags & IFF_NO_PI)) > + printf(" pi"); > + > + if (flags & IFF_ONE_QUEUE) > + printf(" one_queue"); > + > + if (flags & IFF_VNET_HDR) > + printf(" vnet_hdr"); > + > + flags &= ~(IFF_TUN|IFF_TAP|IFF_NO_PI|IFF_ONE_QUEUE|IFF_VNET_HDR); > + if (flags) > + printf(" UNKNOWN_FLAGS:%x", flags); > +} > + > +static int do_show(int argc, char **argv) > +{ > + DIR *dir; > + struct dirent *d; > + long flags, owner = -1, group = -1; > + int i; > + > + dir = opendir("/sys/class/net"); > + if (!dir) { > + perror("opendir"); > + return -1; > + } > + 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"); > + } > + return 0; > +} > + > +int do_iptuntap(int argc, char **argv) > +{ > + if (argc > 0) { > + if (matches(*argv, "add") == 0) > + return do_add(argc-1, argv+1); > + if (matches(*argv, "del") == 0) > + return do_del(argc-1, argv+1); > + if (matches(*argv, "show") == 0 || > + matches(*argv, "lst") == 0 || > + matches(*argv, "list") == 0) > + return do_show(argc-1, argv+1); > + if (matches(*argv, "help") == 0) > + usage(); > + } else > + return do_show(0, NULL); > + > + fprintf(stderr, "Command \"%s\" is unknown, try \"ip tuntap help\".\n", *argv); > + exit(-1); > +} > -- ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-28 4:58 ` Stephen Hemminger @ 2009-05-28 8:12 ` David Woodhouse 2009-06-13 8:55 ` David Woodhouse 0 siblings, 1 reply; 23+ messages in thread From: David Woodhouse @ 2009-05-28 8:12 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On Wed, 2009-05-27 at 21:58 -0700, Stephen Hemminger wrote: > > +#define TUNDEV "/dev/net/tun" > > I know this is historical legacy, but how does this play with network namespaces? For /dev/net/tun itself, it doesn't need to. The namespaces come into play when you issue the TUNSETIFF ioctl to create/attach a particular named device, which uses the network namespace of the process which opened /dev/net/tun. > > +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) > > +{ > > + int fd = open(TUNDEV, O_RDWR); > > + int ret = -1; > > + > > +#ifndef IFF_TUN_EXCL > > +#define IFF_TUN_EXCL 0x8000 > > +#endif > > This shouldn't be here. > It should be defined in include/linux/if_tun.h in kernel source > and then a kernel sanitized version of if_tun.h should be put > in iproute2 source for backwards compatibility. I'm happy to do that; I was just taking my lead from the handling of RTAX_RTTVAR, IP_DF, IPPROTO_SCTP, IPPPROTO_DCCP and IPPROTO_MH in ip/*.c > But why bother it doesn't seem to be defined or used by current kernel?? It's in net-next and is harmless in older kernels. It just means you can't accidentally 'create' a device which already existed. > Would prefer open() next to the test. OK, moved. > > + while (argc > 0) { > > + if (strcmp(*argv, "mode") == 0) { > > The argument parsing in ip commands uses matches() rather than strcmp > to allow for partial completion. OK. I had copied that part from 'ip tunnel', which uses strcmp(). New patch... diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h new file mode 100644 index 0000000..915ba57 --- /dev/null +++ b/include/linux/if_tun.h @@ -0,0 +1,88 @@ +/* + * Universal TUN/TAP device driver. + * Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __IF_TUN_H +#define __IF_TUN_H + +#include <linux/types.h> +#include <linux/if_ether.h> + +/* Read queue size */ +#define TUN_READQ_SIZE 500 + +/* TUN device flags */ +#define TUN_TUN_DEV 0x0001 +#define TUN_TAP_DEV 0x0002 +#define TUN_TYPE_MASK 0x000f + +#define TUN_FASYNC 0x0010 +#define TUN_NOCHECKSUM 0x0020 +#define TUN_NO_PI 0x0040 +#define TUN_ONE_QUEUE 0x0080 +#define TUN_PERSIST 0x0100 +#define TUN_VNET_HDR 0x0200 + +/* Ioctl defines */ +#define TUNSETNOCSUM _IOW('T', 200, int) +#define TUNSETDEBUG _IOW('T', 201, int) +#define TUNSETIFF _IOW('T', 202, int) +#define TUNSETPERSIST _IOW('T', 203, int) +#define TUNSETOWNER _IOW('T', 204, int) +#define TUNSETLINK _IOW('T', 205, int) +#define TUNSETGROUP _IOW('T', 206, int) +#define TUNGETFEATURES _IOR('T', 207, unsigned int) +#define TUNSETOFFLOAD _IOW('T', 208, unsigned int) +#define TUNSETTXFILTER _IOW('T', 209, unsigned int) +#define TUNGETIFF _IOR('T', 210, unsigned int) +#define TUNGETSNDBUF _IOR('T', 211, int) +#define TUNSETSNDBUF _IOW('T', 212, int) + +/* TUNSETIFF ifr flags */ +#define IFF_TUN 0x0001 +#define IFF_TAP 0x0002 +#define IFF_NO_PI 0x1000 +#define IFF_ONE_QUEUE 0x2000 +#define IFF_VNET_HDR 0x4000 +#define IFF_TUN_EXCL 0x8000 + +/* Features for GSO (TUNSETOFFLOAD). */ +#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ +#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */ +#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ +#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ + +/* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ +#define TUN_PKT_STRIP 0x0001 +struct tun_pi { + __u16 flags; + __be16 proto; +}; + +/* + * Filter spec (used for SETXXFILTER ioctls) + * This stuff is applicable only to the TAP (Ethernet) devices. + * If the count is zero the filter is disabled and the driver accepts + * all packets (promisc mode). + * If the filter is enabled in order to accept broadcast packets + * broadcast addr must be explicitly included in the addr list. + */ +#define TUN_FLT_ALLMULTI 0x0001 /* Accept all multicast packets */ +struct tun_filter { + __u16 flags; /* TUN_FLT_ flags see above */ + __u16 count; /* Number of addresses */ + __u8 addr[0][ETH_ALEN]; +}; + +#endif /* __IF_TUN_H */ diff --git a/ip/Makefile b/ip/Makefile index 3c185cf..fd16fe9 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -1,6 +1,6 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \ rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \ - ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \ + ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \ ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ iplink_vlan.o link_veth.o link_gre.o iplink_can.o diff --git a/ip/ip.c b/ip/ip.c index 2bd54b2..d846a76 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -47,7 +47,7 @@ static void usage(void) "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" " ip [ -force ] -batch filename\n" "where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n" -" tunnel | maddr | mroute | monitor | xfrm }\n" +" tunnel | tuntap | maddr | mroute | monitor | xfrm }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -f[amily] { inet | inet6 | ipx | dnet | link } |\n" " -o[neline] | -t[imestamp] | -b[atch] [filename] }\n"); @@ -75,6 +75,8 @@ static const struct cmd { { "link", do_iplink }, { "tunnel", do_iptunnel }, { "tunl", do_iptunnel }, + { "tuntap", do_iptuntap }, + { "tap", do_iptuntap }, { "monitor", do_ipmonitor }, { "xfrm", do_xfrm }, { "mroute", do_multiroute }, diff --git a/ip/ip_common.h b/ip/ip_common.h index 273065f..c857667 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -32,6 +32,7 @@ extern int do_ipneigh(int argc, char **argv); extern int do_ipntable(int argc, char **argv); extern int do_iptunnel(int argc, char **argv); extern int do_ip6tunnel(int argc, char **argv); +extern int do_iptuntap(int argc, char **argv); extern int do_iplink(int argc, char **argv); extern int do_ipmonitor(int argc, char **argv); extern int do_multiaddr(int argc, char **argv); diff --git a/ip/iptuntap.c b/ip/iptuntap.c new file mode 100644 index 0000000..f7f64bc --- /dev/null +++ b/ip/iptuntap.c @@ -0,0 +1,321 @@ +/* + * iptunnel.c "ip tuntap" + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: David Woodhouse <David.Woodhouse@intel.com> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <pwd.h> +#include <grp.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +#define TUNDEV "/dev/net/tun" + +static void usage(void) __attribute__((noreturn)); + +static void usage(void) +{ + fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n"); + fprintf(stderr, " [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"); + fprintf(stderr, " [ one_queue ] [ pi ] [ vnet_hdr ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Where: USER := { STRING | NUMBER }\n"); + fprintf(stderr, " GROUP := { STRING | NUMBER }\n"); + exit(-1); +} + +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) +{ + int fd = open(TUNDEV, O_RDWR); + int ret = -1; + + ifr->ifr_flags |= IFF_TUN_EXCL; + + fd = open(TUNDEV, O_RDWR); + if (fd < 0) { + perror("open"); + return -1; + } + if (ioctl(fd, TUNSETIFF, ifr)) { + perror("ioctl(TUNSETIFF)"); + goto out; + } + if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) { + perror("ioctl(TUNSETOWNER)"); + goto out; + } + if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) { + perror("ioctl(TUNSETGROUP)"); + goto out; + } + if (ioctl(fd, TUNSETPERSIST, 1)) { + perror("ioctl(TUNSETPERSIST)"); + goto out; + } + ret = 0; + out: + close(fd); + return ret; +} + +static int tap_del_ioctl(struct ifreq *ifr) +{ + int fd = open(TUNDEV, O_RDWR); + int ret = -1; + + if (fd < 0) { + perror("open"); + return -1; + } + if (ioctl(fd, TUNSETIFF, ifr)) { + perror("ioctl(TUNSETIFF)"); + goto out; + } + if (ioctl(fd, TUNSETPERSIST, 0)) { + perror("ioctl(TUNSETPERSIST)"); + goto out; + } + ret = 0; + out: + close(fd); + return ret; + +} +static int parse_args(int argc, char **argv, struct ifreq *ifr, uid_t *uid, gid_t *gid) +{ + int count = 0; + + memset(ifr, 0, sizeof(*ifr)); + + ifr->ifr_flags |= IFF_NO_PI; + + while (argc > 0) { + if (matches(*argv, "mode") == 0) { + NEXT_ARG(); + if (matches(*argv, "tun") == 0) { + if (ifr->ifr_flags & IFF_TAP) { + fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); + exit(-1); + } + ifr->ifr_flags |= IFF_TUN; + } else if (matches(*argv, "tap") == 0) { + if (ifr->ifr_flags & IFF_TUN) { + fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); + exit(-1); + } + ifr->ifr_flags |= IFF_TAP; + } else { + fprintf(stderr,"Cannot guess tunnel mode.\n"); + exit(-1); + } + } else if (uid && matches(*argv, "user") == 0) { + char *end; + unsigned long user; + + NEXT_ARG(); + if (**argv && ((user = strtol(*argv, &end, 10)), !*end)) + *uid = user; + else { + struct passwd *pw = getpwnam(*argv); + if (!pw) { + fprintf(stderr, "invalid user \"%s\"\n", *argv); + exit(-1); + } + *uid = pw->pw_uid; + } + } else if (gid && matches(*argv, "group") == 0) { + char *end; + unsigned long group; + + NEXT_ARG(); + + if (**argv && ((group = strtol(*argv, &end, 10)), !*end)) + *gid = group; + else { + struct group *gr = getgrnam(*argv); + if (!gr) { + fprintf(stderr, "invalid group \"%s\"\n", *argv); + exit(-1); + } + *gid = gr->gr_gid; + } + } else if (matches(*argv, "pi") == 0) { + ifr->ifr_flags &= ~IFF_NO_PI; + } else if (matches(*argv, "one_queue") == 0) { + ifr->ifr_flags |= IFF_ONE_QUEUE; + } else if (matches(*argv, "vnet_hdr") == 0) { + ifr->ifr_flags |= IFF_VNET_HDR; + } else if (matches(*argv, "dev") == 0) { + NEXT_ARG(); + strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1); + } else { + if (matches(*argv, "name") == 0) { + NEXT_ARG(); + } else if (matches(*argv, "help") == 0) + usage(); + if (ifr->ifr_name[0]) + duparg2("name", *argv); + strncpy(ifr->ifr_name, *argv, IFNAMSIZ); + } + count++; + argc--; argv++; + } + + return 0; +} + + +static int do_add(int argc, char **argv) +{ + struct ifreq ifr; + uid_t uid = -1; + gid_t gid = -1; + + if (parse_args(argc, argv, &ifr, &uid, &gid) < 0) + return -1; + + if (!(ifr.ifr_flags & TUN_TYPE_MASK)) { + fprintf(stderr, "You failed to specify a tunnel mode\n"); + return -1; + } + return tap_add_ioctl(&ifr, uid, gid); +} + +static int do_del(int argc, char **argv) +{ + struct ifreq ifr; + + if (parse_args(argc, argv, &ifr, NULL, NULL) < 0) + return -1; + + return tap_del_ioctl(&ifr); +} + +static int read_prop(char *dev, char *prop, long *value) +{ + char fname[IFNAMSIZ+25], buf[80], *endp; + ssize_t len; + int fd; + long result; + + sprintf(fname, "/sys/class/net/%s/%s", dev, prop); + fd = open(fname, O_RDONLY); + if (fd < 0) { + if (strcmp(prop, "tun_flags")) + fprintf(stderr, "open %s: %s\n", fname, + strerror(errno)); + return -1; + } + len = read(fd, buf, sizeof(buf)-1); + close(fd); + if (len < 0) { + fprintf(stderr, "read %s: %s", fname, strerror(errno)); + return -1; + } + + buf[len] = 0; + result = strtol(buf, &endp, 0); + if (*endp != '\n') { + fprintf(stderr, "Failed to parse %s\n", fname); + return -1; + } + *value = result; + return 0; +} + +static void print_flags(long flags) +{ + if (flags & IFF_TUN) + printf(" tun"); + + if (flags & IFF_TAP) + printf(" tap"); + + if (!(flags & IFF_NO_PI)) + printf(" pi"); + + if (flags & IFF_ONE_QUEUE) + printf(" one_queue"); + + if (flags & IFF_VNET_HDR) + printf(" vnet_hdr"); + + flags &= ~(IFF_TUN|IFF_TAP|IFF_NO_PI|IFF_ONE_QUEUE|IFF_VNET_HDR); + if (flags) + printf(" UNKNOWN_FLAGS:%lx", flags); +} + +static int do_show(int argc, char **argv) +{ + DIR *dir; + struct dirent *d; + long flags, owner = -1, group = -1; + + dir = opendir("/sys/class/net"); + if (!dir) { + perror("opendir"); + return -1; + } + 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"); + } + return 0; +} + +int do_iptuntap(int argc, char **argv) +{ + if (argc > 0) { + if (matches(*argv, "add") == 0) + return do_add(argc-1, argv+1); + if (matches(*argv, "del") == 0) + return do_del(argc-1, argv+1); + if (matches(*argv, "show") == 0 || + matches(*argv, "lst") == 0 || + matches(*argv, "list") == 0) + return do_show(argc-1, argv+1); + if (matches(*argv, "help") == 0) + usage(); + } else + return do_show(0, NULL); + + fprintf(stderr, "Command \"%s\" is unknown, try \"ip tuntap help\".\n", + *argv); + exit(-1); +} -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-05-28 8:12 ` David Woodhouse @ 2009-06-13 8:55 ` David Woodhouse 2009-07-20 23:44 ` David Woodhouse 0 siblings, 1 reply; 23+ messages in thread From: David Woodhouse @ 2009-06-13 8:55 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On Thu, 2009-05-28 at 09:12 +0100, David Woodhouse wrote: > On Wed, 2009-05-27 at 21:58 -0700, Stephen Hemminger wrote: > > > +#define TUNDEV "/dev/net/tun" > > > > I know this is historical legacy, but how does this play with > network namespaces? > > For /dev/net/tun itself, it doesn't need to. The namespaces come into > play when you issue the TUNSETIFF ioctl to create/attach a particular > named device, which uses the network namespace of the process which > opened /dev/net/tun. > > > > +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) > > > +{ > > > + int fd = open(TUNDEV, O_RDWR); > > > + int ret = -1; > > > + > > > +#ifndef IFF_TUN_EXCL > > > +#define IFF_TUN_EXCL 0x8000 > > > +#endif > > > > This shouldn't be here. > > It should be defined in include/linux/if_tun.h in kernel source > > and then a kernel sanitized version of if_tun.h should be put > > in iproute2 source for backwards compatibility. > > I'm happy to do that; I was just taking my lead from the handling of > RTAX_RTTVAR, IP_DF, IPPROTO_SCTP, IPPPROTO_DCCP and IPPROTO_MH in > ip/*.c > > > But why bother it doesn't seem to be defined or used by current > kernel?? > > It's in net-next and is harmless in older kernels. It just means you > can't accidentally 'create' a device which already existed. > > > Would prefer open() next to the test. > > OK, moved. > > > > + while (argc > 0) { > > > + if (strcmp(*argv, "mode") == 0) { > > > > The argument parsing in ip commands uses matches() rather than > strcmp > > to allow for partial completion. > > OK. I had copied that part from 'ip tunnel', which uses strcmp(). > > New patch... Ping? -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices 2009-06-13 8:55 ` David Woodhouse @ 2009-07-20 23:44 ` David Woodhouse 0 siblings, 0 replies; 23+ messages in thread From: David Woodhouse @ 2009-07-20 23:44 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On Sat, 2009-06-13 at 09:55 +0100, David Woodhouse wrote: > On Thu, 2009-05-28 at 09:12 +0100, David Woodhouse wrote: > > On Wed, 2009-05-27 at 21:58 -0700, Stephen Hemminger wrote: > > > > +#define TUNDEV "/dev/net/tun" > > > > > > I know this is historical legacy, but how does this play with > > network namespaces? > > > > For /dev/net/tun itself, it doesn't need to. The namespaces come into > > play when you issue the TUNSETIFF ioctl to create/attach a particular > > named device, which uses the network namespace of the process which > > opened /dev/net/tun. > > > > > > +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid) > > > > +{ > > > > + int fd = open(TUNDEV, O_RDWR); > > > > + int ret = -1; > > > > + > > > > +#ifndef IFF_TUN_EXCL > > > > +#define IFF_TUN_EXCL 0x8000 > > > > +#endif > > > > > > This shouldn't be here. > > > It should be defined in include/linux/if_tun.h in kernel source > > > and then a kernel sanitized version of if_tun.h should be put > > > in iproute2 source for backwards compatibility. > > > > I'm happy to do that; I was just taking my lead from the handling of > > RTAX_RTTVAR, IP_DF, IPPROTO_SCTP, IPPPROTO_DCCP and IPPROTO_MH in > > ip/*.c > > > > > But why bother it doesn't seem to be defined or used by current > > kernel?? > > > > It's in net-next and is harmless in older kernels. It just means you > > can't accidentally 'create' a device which already existed. > > > > > Would prefer open() next to the test. > > > > OK, moved. > > > > > > + while (argc > 0) { > > > > + if (strcmp(*argv, "mode") == 0) { > > > > > > The argument parsing in ip commands uses matches() rather than > > strcmp > > > to allow for partial completion. > > > > OK. I had copied that part from 'ip tunnel', which uses strcmp(). > > > > New patch... > > Ping? Ping? -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-04 10:32 tun: add tun_flags, owner, group attributes in sysfs David Woodhouse 2009-05-04 10:36 ` Michael Tokarev 2009-05-04 10:42 ` [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices David Woodhouse @ 2009-05-04 14:47 ` Stephen Hemminger 2009-05-04 14:58 ` David Woodhouse 2009-05-09 20:27 ` David Miller 2009-05-10 5:54 ` David Miller 4 siblings, 1 reply; 23+ messages in thread From: Stephen Hemminger @ 2009-05-04 14:47 UTC (permalink / raw) To: David Woodhouse; +Cc: netdev, Mark McLoughlin On Mon, 04 May 2009 11:32:16 +0100 David Woodhouse <dwmw2@infradead.org> wrote: > This patch adds three attribute files in /sys/class/net/$dev/ for tun > devices; allowing userspace to obtain the information which TUNGETIFF > offers, and more, but without having to attach to the device in question > (which may not be possible if it's in use). > > It also fixes a bug which has been present in the TUNGETIFF ioctl since > its inception, where it would never set IFF_TUN or IFF_TAP according to > the device type. (Look carefully at the code which I remove from > tun_get_iff() and how the new tun_flags() helper is subtly different). > > Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> > --- > I don't have to explicitly remove the files, do I? They go away > naturally when the device is unregistered? > > diff --git a/drivers/net/tun.c b/drivers/net/tun.c > index 94622e5..4cda69b 100644 > --- a/drivers/net/tun.c > +++ b/drivers/net/tun.c > @@ -865,6 +865,52 @@ static struct proto tun_proto = { > .obj_size = sizeof(struct tun_sock), > }; > > +static int tun_flags(struct tun_struct *tun) > +{ > + int flags = 0; > + > + if (tun->flags & TUN_TUN_DEV) > + flags |= IFF_TUN; > + else > + flags |= IFF_TAP; > + > + if (tun->flags & TUN_NO_PI) > + flags |= IFF_NO_PI; > + > + if (tun->flags & TUN_ONE_QUEUE) > + flags |= IFF_ONE_QUEUE; > + > + if (tun->flags & TUN_VNET_HDR) > + flags |= IFF_VNET_HDR; > + > + return flags; > +} > + > +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); > + return sprintf(buf, "0x%x\n", tun_flags(tun)); > +} > + > +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); > + return sprintf(buf, "%d\n", tun->owner); > +} > + > +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); > + return sprintf(buf, "%d\n", tun->group); > +} > + > +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); > +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); > +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); > + > static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) > { > struct sock *sk; > @@ -950,6 +996,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) > if (err < 0) > goto err_free_sk; > > + if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || > + device_create_file(&tun->dev->dev, &dev_attr_owner) || > + device_create_file(&tun->dev->dev, &dev_attr_group)) > + printk(KERN_ERR "Failed to create tun sysfs files\n"); > + > sk->sk_destruct = tun_sock_destruct; > > err = tun_attach(tun, file); > @@ -1002,21 +1053,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) > > strcpy(ifr->ifr_name, tun->dev->name); > > - ifr->ifr_flags = 0; > - > - if (ifr->ifr_flags & TUN_TUN_DEV) > - ifr->ifr_flags |= IFF_TUN; > - else > - ifr->ifr_flags |= IFF_TAP; > - > - if (tun->flags & TUN_NO_PI) > - ifr->ifr_flags |= IFF_NO_PI; > - > - if (tun->flags & TUN_ONE_QUEUE) > - ifr->ifr_flags |= IFF_ONE_QUEUE; > - > - if (tun->flags & TUN_VNET_HDR) > - ifr->ifr_flags |= IFF_VNET_HDR; > + ifr->ifr_flags = tun_flags(tun); > > tun_put(tun); > return 0; Netlink please not sysfs. also, any sysfs attributes have to handle unregistration issues. ( sleep 900; read owner ) </sys/class/net/tun0/owner & rmmod tun ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-04 14:47 ` tun: add tun_flags, owner, group attributes in sysfs Stephen Hemminger @ 2009-05-04 14:58 ` David Woodhouse 0 siblings, 0 replies; 23+ messages in thread From: David Woodhouse @ 2009-05-04 14:58 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev, Mark McLoughlin On Mon, 2009-05-04 at 07:47 -0700, Stephen Hemminger wrote: > Netlink please not sysfs. That seems like overkill in this case. > also, any sysfs attributes have to handle unregistration issues. > ( sleep 900; read owner ) </sys/class/net/tun0/owner & > rmmod tun That gets handled for you automatically... [root@tylersburg ~]# ( sleep 900 ; read owner; echo $owner ) < /sys/class/net/tun0/owner & [1] 4728 [root@tylersburg ~]# ./ip tuntap del tun0 mode tun [root@tylersburg ~]# rmmod tun [root@tylersburg ~]# killall sleep -bash: line 28: 4729 Terminated sleep 900 [root@tylersburg ~]# -bash: line 28: read: read error: 0: No such device -- dwmw2 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-04 10:32 tun: add tun_flags, owner, group attributes in sysfs David Woodhouse ` (2 preceding siblings ...) 2009-05-04 14:47 ` tun: add tun_flags, owner, group attributes in sysfs Stephen Hemminger @ 2009-05-09 20:27 ` David Miller 2009-05-09 22:27 ` David Woodhouse 2009-05-10 5:54 ` David Miller 4 siblings, 1 reply; 23+ messages in thread From: David Miller @ 2009-05-09 20:27 UTC (permalink / raw) To: dwmw2; +Cc: netdev, markmc From: David Woodhouse <dwmw2@infradead.org> Date: Mon, 04 May 2009 11:32:16 +0100 > I don't have to explicitly remove the files, do I? They go away > naturally when the device is unregistered? I'm not so sure about this. I can't see anything in the drivers/base/core.c code that automatically deletes anything other than device groups and attributes. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-09 20:27 ` David Miller @ 2009-05-09 22:27 ` David Woodhouse 2009-05-09 22:55 ` David Woodhouse 2009-05-09 22:56 ` David Miller 0 siblings, 2 replies; 23+ messages in thread From: David Woodhouse @ 2009-05-09 22:27 UTC (permalink / raw) To: David Miller; +Cc: netdev, markmc On Sat, 2009-05-09 at 13:27 -0700, David Miller wrote: > From: David Woodhouse <dwmw2@infradead.org> > Date: Mon, 04 May 2009 11:32:16 +0100 > > > I don't have to explicitly remove the files, do I? They go away > > naturally when the device is unregistered? > > I'm not so sure about this. I can't see anything in the > drivers/base/core.c code that automatically deletes anything > other than device groups and attributes. Hm, I really do think the attributes go away automatically when the parent device does. If not, gianfar_sysfs.c and niu.c want fixing too -- and we should probably have a WARN_ON() in the sysfs code when it happens, if possible. I'll experiment (since I'm getting lost when I try to work it out by inspection). -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-09 22:27 ` David Woodhouse @ 2009-05-09 22:55 ` David Woodhouse 2009-05-09 22:56 ` David Miller 1 sibling, 0 replies; 23+ messages in thread From: David Woodhouse @ 2009-05-09 22:55 UTC (permalink / raw) To: David Miller; +Cc: netdev, markmc On Sat, 2009-05-09 at 23:27 +0100, David Woodhouse wrote: > On Sat, 2009-05-09 at 13:27 -0700, David Miller wrote: > > From: David Woodhouse <dwmw2@infradead.org> > > Date: Mon, 04 May 2009 11:32:16 +0100 > > > > > I don't have to explicitly remove the files, do I? They go away > > > naturally when the device is unregistered? > > > > I'm not so sure about this. I can't see anything in the > > drivers/base/core.c code that automatically deletes anything > > other than device groups and attributes. > > Hm, I really do think the attributes go away automatically when the > parent device does. > > If not, gianfar_sysfs.c and niu.c want fixing too -- and we should > probably have a WARN_ON() in the sysfs code when it happens, if > possible. > > I'll experiment (since I'm getting lost when I try to work it out by > inspection). I added a WARN_ON(!strcmp(sd->s_name, "tun_flags")) into release_sysfs_dirent() to see when (and if) it gets called. It does. Looking at the backtrace, I see it's __sysfs_remove_dir() which iterates over all the children of the device's directory and kills them: [ 98.024138] [<ffffffff810f2e4e>] release_sysfs_dirent+0x49/0xc8 [ 98.030178] [<ffffffff810f2eff>] __sysfs_put+0x32/0x36 [ 98.035432] [<ffffffff810f3133>] sysfs_addrm_finish+0x20c/0x239 [ 98.041470] [<ffffffff810f2870>] ? sysfs_ilookup_test+0x0/0x14 [ 98.047417] [<ffffffff810f3214>] sysfs_remove_dir+0x6f/0x82 [ 98.053107] [<ffffffff8118fce4>] kobject_del+0x16/0x37 [ 98.058367] [<ffffffff8123953f>] device_del+0x16b/0x17b [ 98.063769] [<ffffffff813b2d8f>] netdev_unregister_kobject+0x24/0x29 [ 98.070241] [<ffffffff813a7f0f>] rollback_registered+0x1d2/0x1e3 [ 98.076364] [<ffffffff813a7f5a>] unregister_netdevice+0x3a/0x69 [ 98.082402] [<ffffffffa0006458>] tun_chr_close+0x3d/0x66 [tun] -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-09 22:27 ` David Woodhouse 2009-05-09 22:55 ` David Woodhouse @ 2009-05-09 22:56 ` David Miller 1 sibling, 0 replies; 23+ messages in thread From: David Miller @ 2009-05-09 22:56 UTC (permalink / raw) To: dwmw2; +Cc: netdev, markmc From: David Woodhouse <dwmw2@infradead.org> Date: Sat, 09 May 2009 23:27:53 +0100 > I'll experiment (since I'm getting lost when I try to work it out by > inspection). Thanks David. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: tun: add tun_flags, owner, group attributes in sysfs 2009-05-04 10:32 tun: add tun_flags, owner, group attributes in sysfs David Woodhouse ` (3 preceding siblings ...) 2009-05-09 20:27 ` David Miller @ 2009-05-10 5:54 ` David Miller 4 siblings, 0 replies; 23+ messages in thread From: David Miller @ 2009-05-10 5:54 UTC (permalink / raw) To: dwmw2; +Cc: netdev, markmc From: David Woodhouse <dwmw2@infradead.org> Date: Mon, 04 May 2009 11:32:16 +0100 > This patch adds three attribute files in /sys/class/net/$dev/ for tun > devices; allowing userspace to obtain the information which TUNGETIFF > offers, and more, but without having to attach to the device in question > (which may not be possible if it's in use). > > It also fixes a bug which has been present in the TUNGETIFF ioctl since > its inception, where it would never set IFF_TUN or IFF_TAP according to > the device type. (Look carefully at the code which I remove from > tun_get_iff() and how the new tun_flags() helper is subtly different). > > Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Applied to net-next-2.6, thanks! ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2009-07-20 23:44 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-05-04 10:32 tun: add tun_flags, owner, group attributes in sysfs David Woodhouse 2009-05-04 10:36 ` Michael Tokarev 2009-05-05 22:18 ` David Woodhouse 2009-05-04 10:42 ` [iproute2 patch]: Add 'ip tuntap' facility for managing tun/tap devices David Woodhouse 2009-05-04 14:38 ` Stephen Hemminger 2009-05-04 14:49 ` David Woodhouse 2009-05-27 16:32 ` David Woodhouse 2009-05-27 16:38 ` Stephen Hemminger 2009-05-27 16:49 ` David Woodhouse 2009-05-27 17:06 ` Stephen Hemminger 2009-05-27 20:44 ` David Miller 2009-05-27 20:43 ` David Miller 2009-05-28 4:58 ` Stephen Hemminger 2009-05-28 8:12 ` David Woodhouse 2009-06-13 8:55 ` David Woodhouse 2009-07-20 23:44 ` David Woodhouse 2009-05-04 14:47 ` tun: add tun_flags, owner, group attributes in sysfs Stephen Hemminger 2009-05-04 14:58 ` David Woodhouse 2009-05-09 20:27 ` David Miller 2009-05-09 22:27 ` David Woodhouse 2009-05-09 22:55 ` David Woodhouse 2009-05-09 22:56 ` David Miller 2009-05-10 5:54 ` David Miller
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).