aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-05-10 01:54:21 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-10 01:54:21 -0400
commit980c9e8ceeb69ac4c921173d0d06323f5c678647 (patch)
tree6dc3a40501bf94177f40009cea3327dcb70462cb /drivers/net/tun.c
parented9b58bc443a1210b5be1ded6421b17e015bf985 (diff)
tun: add tun_flags, owner, group attributes in sysfs
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> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c67
1 files changed, 52 insertions, 15 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 94622e5fb936..4cda69b6b28c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -865,6 +865,52 @@ static struct proto tun_proto = {
865 .obj_size = sizeof(struct tun_sock), 865 .obj_size = sizeof(struct tun_sock),
866}; 866};
867 867
868static int tun_flags(struct tun_struct *tun)
869{
870 int flags = 0;
871
872 if (tun->flags & TUN_TUN_DEV)
873 flags |= IFF_TUN;
874 else
875 flags |= IFF_TAP;
876
877 if (tun->flags & TUN_NO_PI)
878 flags |= IFF_NO_PI;
879
880 if (tun->flags & TUN_ONE_QUEUE)
881 flags |= IFF_ONE_QUEUE;
882
883 if (tun->flags & TUN_VNET_HDR)
884 flags |= IFF_VNET_HDR;
885
886 return flags;
887}
888
889static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr,
890 char *buf)
891{
892 struct tun_struct *tun = netdev_priv(to_net_dev(dev));
893 return sprintf(buf, "0x%x\n", tun_flags(tun));
894}
895
896static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
897 char *buf)
898{
899 struct tun_struct *tun = netdev_priv(to_net_dev(dev));
900 return sprintf(buf, "%d\n", tun->owner);
901}
902
903static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
904 char *buf)
905{
906 struct tun_struct *tun = netdev_priv(to_net_dev(dev));
907 return sprintf(buf, "%d\n", tun->group);
908}
909
910static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL);
911static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL);
912static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
913
868static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) 914static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
869{ 915{
870 struct sock *sk; 916 struct sock *sk;
@@ -950,6 +996,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
950 if (err < 0) 996 if (err < 0)
951 goto err_free_sk; 997 goto err_free_sk;
952 998
999 if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
1000 device_create_file(&tun->dev->dev, &dev_attr_owner) ||
1001 device_create_file(&tun->dev->dev, &dev_attr_group))
1002 printk(KERN_ERR "Failed to create tun sysfs files\n");
1003
953 sk->sk_destruct = tun_sock_destruct; 1004 sk->sk_destruct = tun_sock_destruct;
954 1005
955 err = tun_attach(tun, file); 1006 err = tun_attach(tun, file);
@@ -1002,21 +1053,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
1002 1053
1003 strcpy(ifr->ifr_name, tun->dev->name); 1054 strcpy(ifr->ifr_name, tun->dev->name);
1004 1055
1005 ifr->ifr_flags = 0; 1056 ifr->ifr_flags = tun_flags(tun);
1006
1007 if (ifr->ifr_flags & TUN_TUN_DEV)
1008 ifr->ifr_flags |= IFF_TUN;
1009 else
1010 ifr->ifr_flags |= IFF_TAP;
1011
1012 if (tun->flags & TUN_NO_PI)
1013 ifr->ifr_flags |= IFF_NO_PI;
1014
1015 if (tun->flags & TUN_ONE_QUEUE)
1016 ifr->ifr_flags |= IFF_ONE_QUEUE;
1017
1018 if (tun->flags & TUN_VNET_HDR)
1019 ifr->ifr_flags |= IFF_VNET_HDR;
1020 1057
1021 tun_put(tun); 1058 tun_put(tun);
1022 return 0; 1059 return 0;