tun: export flags, uid, gid, queue information over netlink
authorSabrina Dubroca <sd@queasysnail.net>
Fri, 16 Feb 2018 10:03:07 +0000 (11:03 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Feb 2018 21:58:22 +0000 (16:58 -0500)
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/tun.c
include/uapi/linux/if_link.h

index 8e9a0ac..86b1601 100644 (file)
@@ -2291,11 +2291,67 @@ static int tun_validate(struct nlattr *tb[], struct nlattr *data[],
        return -EINVAL;
 }
 
+static size_t tun_get_size(const struct net_device *dev)
+{
+       BUILD_BUG_ON(sizeof(u32) != sizeof(uid_t));
+       BUILD_BUG_ON(sizeof(u32) != sizeof(gid_t));
+
+       return nla_total_size(sizeof(uid_t)) + /* OWNER */
+              nla_total_size(sizeof(gid_t)) + /* GROUP */
+              nla_total_size(sizeof(u8)) + /* TYPE */
+              nla_total_size(sizeof(u8)) + /* PI */
+              nla_total_size(sizeof(u8)) + /* VNET_HDR */
+              nla_total_size(sizeof(u8)) + /* PERSIST */
+              nla_total_size(sizeof(u8)) + /* MULTI_QUEUE */
+              nla_total_size(sizeof(u32)) + /* NUM_QUEUES */
+              nla_total_size(sizeof(u32)) + /* NUM_DISABLED_QUEUES */
+              0;
+}
+
+static int tun_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+
+       if (nla_put_u8(skb, IFLA_TUN_TYPE, tun->flags & TUN_TYPE_MASK))
+               goto nla_put_failure;
+       if (uid_valid(tun->owner) &&
+           nla_put_u32(skb, IFLA_TUN_OWNER,
+                       from_kuid_munged(current_user_ns(), tun->owner)))
+               goto nla_put_failure;
+       if (gid_valid(tun->group) &&
+           nla_put_u32(skb, IFLA_TUN_GROUP,
+                       from_kgid_munged(current_user_ns(), tun->group)))
+               goto nla_put_failure;
+       if (nla_put_u8(skb, IFLA_TUN_PI, !(tun->flags & IFF_NO_PI)))
+               goto nla_put_failure;
+       if (nla_put_u8(skb, IFLA_TUN_VNET_HDR, !!(tun->flags & IFF_VNET_HDR)))
+               goto nla_put_failure;
+       if (nla_put_u8(skb, IFLA_TUN_PERSIST, !!(tun->flags & IFF_PERSIST)))
+               goto nla_put_failure;
+       if (nla_put_u8(skb, IFLA_TUN_MULTI_QUEUE,
+                      !!(tun->flags & IFF_MULTI_QUEUE)))
+               goto nla_put_failure;
+       if (tun->flags & IFF_MULTI_QUEUE) {
+               if (nla_put_u32(skb, IFLA_TUN_NUM_QUEUES, tun->numqueues))
+                       goto nla_put_failure;
+               if (nla_put_u32(skb, IFLA_TUN_NUM_DISABLED_QUEUES,
+                               tun->numdisabled))
+                       goto nla_put_failure;
+       }
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
 static struct rtnl_link_ops tun_link_ops __read_mostly = {
        .kind           = DRV_NAME,
        .priv_size      = sizeof(struct tun_struct),
        .setup          = tun_setup,
        .validate       = tun_validate,
+       .get_size       = tun_get_size,
+       .fill_info      = tun_fill_info,
 };
 
 static void tun_sock_write_space(struct sock *sk)
index 6d94477..11d0c0e 100644 (file)
@@ -941,4 +941,22 @@ enum {
        IFLA_EVENT_BONDING_OPTIONS,     /* change in bonding options */
 };
 
+/* tun section */
+
+enum {
+       IFLA_TUN_UNSPEC,
+       IFLA_TUN_OWNER,
+       IFLA_TUN_GROUP,
+       IFLA_TUN_TYPE,
+       IFLA_TUN_PI,
+       IFLA_TUN_VNET_HDR,
+       IFLA_TUN_PERSIST,
+       IFLA_TUN_MULTI_QUEUE,
+       IFLA_TUN_NUM_QUEUES,
+       IFLA_TUN_NUM_DISABLED_QUEUES,
+       __IFLA_TUN_MAX,
+};
+
+#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1)
+
 #endif /* _UAPI_LINUX_IF_LINK_H */