netlink/diag: report flags for netlink sockets
authorAndrey Vagin <avagin@openvz.org>
Tue, 4 Apr 2017 01:13:32 +0000 (18:13 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Apr 2017 14:13:56 +0000 (07:13 -0700)
cb_running is reported in /proc/self/net/netlink and it is reported by
the ss tool, when it gets information from the proc files.

sock_diag is a new interface which is used instead of proc files, so it
looks reasonable that this interface has to report no less information
about sockets than proc files.

We use these flags to dump and restore netlink sockets.

Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/netlink_diag.h
net/netlink/af_netlink.c
net/netlink/af_netlink.h
net/netlink/diag.c

index 76b4d87c83a863dc7b0e809f5ab318b9656d1dfb..6dcd4de3397b393eb64c9da83e898484af65fda9 100644 (file)
@@ -38,6 +38,7 @@ enum {
        NETLINK_DIAG_GROUPS,
        NETLINK_DIAG_RX_RING,
        NETLINK_DIAG_TX_RING,
+       NETLINK_DIAG_FLAGS,
 
        __NETLINK_DIAG_MAX,
 };
@@ -52,5 +53,14 @@ enum {
 /* deprecated since 4.6 */
 #define NDIAG_SHOW_RING_CFG    0x00000004 /* show ring configuration */
 #endif
+#define NDIAG_SHOW_FLAGS       0x00000008 /* show flags of a netlink socket */
+
+/* flags */
+#define NDIAG_FLAG_CB_RUNNING          0x00000001
+#define NDIAG_FLAG_PKTINFO             0x00000002
+#define NDIAG_FLAG_BROADCAST_ERROR     0x00000004
+#define NDIAG_FLAG_NO_ENOBUFS          0x00000008
+#define NDIAG_FLAG_LISTEN_ALL_NSID     0x00000010
+#define NDIAG_FLAG_CAP_ACK             0x00000020
 
 #endif
index 596eaff66649e5955d6c0f349f062b6d8360dc2d..fc232441cf230faacdebf83fd1735462a6453d03 100644 (file)
@@ -78,14 +78,6 @@ struct listeners {
 /* state bits */
 #define NETLINK_S_CONGESTED            0x0
 
-/* flags */
-#define NETLINK_F_KERNEL_SOCKET                0x1
-#define NETLINK_F_RECV_PKTINFO         0x2
-#define NETLINK_F_BROADCAST_SEND_ERROR 0x4
-#define NETLINK_F_RECV_NO_ENOBUFS      0x8
-#define NETLINK_F_LISTEN_ALL_NSID      0x10
-#define NETLINK_F_CAP_ACK              0x20
-
 static inline int netlink_is_kernel(struct sock *sk)
 {
        return nlk_sk(sk)->flags & NETLINK_F_KERNEL_SOCKET;
index 4fdb3831897775547f77c069a8018c0d2a253c8c..f792f8d7f982d3e7d5b67b7cf1c5f01475728e1f 100644 (file)
@@ -6,6 +6,14 @@
 #include <linux/workqueue.h>
 #include <net/sock.h>
 
+/* flags */
+#define NETLINK_F_KERNEL_SOCKET                0x1
+#define NETLINK_F_RECV_PKTINFO         0x2
+#define NETLINK_F_BROADCAST_SEND_ERROR 0x4
+#define NETLINK_F_RECV_NO_ENOBUFS      0x8
+#define NETLINK_F_LISTEN_ALL_NSID      0x10
+#define NETLINK_F_CAP_ACK              0x20
+
 #define NLGRPSZ(x)     (ALIGN(x, sizeof(unsigned long) * 8) / 8)
 #define NLGRPLONGS(x)  (NLGRPSZ(x)/sizeof(unsigned long))
 
index a5546249fb1022b52144a40717b8a4268755b972..8faa20b4d4573f3e2b510f03f3d4a85a70352559 100644 (file)
@@ -19,6 +19,27 @@ static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb)
                       nlk->groups);
 }
 
+static int sk_diag_put_flags(struct sock *sk, struct sk_buff *skb)
+{
+       struct netlink_sock *nlk = nlk_sk(sk);
+       u32 flags = 0;
+
+       if (nlk->cb_running)
+               flags |= NDIAG_FLAG_CB_RUNNING;
+       if (nlk->flags & NETLINK_F_RECV_PKTINFO)
+               flags |= NDIAG_FLAG_PKTINFO;
+       if (nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR)
+               flags |= NDIAG_FLAG_BROADCAST_ERROR;
+       if (nlk->flags & NETLINK_F_RECV_NO_ENOBUFS)
+               flags |= NDIAG_FLAG_NO_ENOBUFS;
+       if (nlk->flags & NETLINK_F_LISTEN_ALL_NSID)
+               flags |= NDIAG_FLAG_LISTEN_ALL_NSID;
+       if (nlk->flags & NETLINK_F_CAP_ACK)
+               flags |= NDIAG_FLAG_CAP_ACK;
+
+       return nla_put_u32(skb, NETLINK_DIAG_FLAGS, flags);
+}
+
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
                        struct netlink_diag_req *req,
                        u32 portid, u32 seq, u32 flags, int sk_ino)
@@ -52,6 +73,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
            sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO))
                goto out_nlmsg_trim;
 
+       if ((req->ndiag_show & NDIAG_SHOW_FLAGS) &&
+           sk_diag_put_flags(sk, skb))
+               goto out_nlmsg_trim;
+
        nlmsg_end(skb, nlh);
        return 0;