]> granicus.if.org Git - strace/blobdiff - netlink_sock_diag.c
Unify different generic PRINT_FIELD_* implementations
[strace] / netlink_sock_diag.c
index 60c8627b26ad587df135a921c9c345f02d434117..3888934974051c50bb601fd57798bafceb66ac81 100644 (file)
@@ -30,6 +30,7 @@
 #include "defs.h"
 #include "netlink.h"
 #include "nlattr.h"
+#include "print_fields.h"
 
 #include <arpa/inet.h>
 #include <linux/inet_diag.h>
@@ -38,6 +39,7 @@
 #ifdef AF_SMC
 # include <linux/smc_diag.h>
 #endif
+#include <linux/sock_diag.h>
 #include <linux/unix_diag.h>
 
 #include "xlat/inet_diag_attrs.h"
@@ -49,6 +51,7 @@
 
 #include "xlat/netlink_diag_attrs.h"
 #include "xlat/netlink_diag_show.h"
+#include "xlat/netlink_socket_flags.h"
 #include "xlat/netlink_states.h"
 
 #include "xlat/packet_diag_attrs.h"
 #include "xlat/unix_diag_attrs.h"
 #include "xlat/unix_diag_show.h"
 
-#define PRINT_FIELD_U(prefix_, where_, field_)                         \
-       tprintf("%s%s=%llu", (prefix_), #field_,                        \
-               zero_extend_signed_to_ull((where_).field_))
-
-#define PRINT_FIELD_COOKIE(prefix_, where_, field_)                    \
-       tprintf("%s%s=[%llu, %llu]", (prefix_), #field_,                \
-               zero_extend_signed_to_ull((where_).field_[0]),          \
-               zero_extend_signed_to_ull((where_).field_[1]))
-
-#define PRINT_FIELD_FLAGS(prefix_, where_, field_, xlat_, dflt_)       \
-       do {                                                            \
-               tprintf("%s%s=", (prefix_), #field_);                   \
-               printflags((xlat_), (where_).field_, (dflt_));          \
-       } while (0)
-
-#define PRINT_FIELD_XVAL(prefix_, where_, field_, xlat_, dflt_)                \
-       do {                                                            \
-               tprintf("%s%s=", (prefix_), #field_);                   \
-               printxval((xlat_), (where_).field_, (dflt_));           \
-       } while (0)
-
 static void
 decode_family(struct tcb *const tcp, const uint8_t family,
              const kernel_ulong_t addr, const kernel_ulong_t len)
@@ -127,6 +109,118 @@ decode_unix_diag_req(struct tcb *const tcp,
        tprints("}");
 }
 
+static bool
+print_meminfo(struct tcb *const tcp,
+             void *const elem_buf,
+             const size_t elem_size,
+             void *const opaque_data)
+{
+       tprintf("%" PRIu32, *(uint32_t *) elem_buf);
+
+       return true;
+}
+
+static bool
+decode_meminfo(struct tcb *const tcp,
+              const kernel_ulong_t addr,
+              const kernel_ulong_t len,
+              const void *const opaque_data)
+{
+       uint32_t mem;
+       size_t nmemb = len / sizeof(mem);
+
+       if (!nmemb)
+               return false;
+
+       if (nmemb > SK_MEMINFO_VARS)
+               nmemb = SK_MEMINFO_VARS;
+
+       print_array(tcp, addr, nmemb, &mem, sizeof(mem),
+                   umoven_or_printaddr, print_meminfo, 0);
+
+       return true;
+}
+
+static bool
+decode_unix_diag_vfs(struct tcb *const tcp,
+                    const kernel_ulong_t addr,
+                    const kernel_ulong_t len,
+                    const void *const opaque_data)
+{
+       struct unix_diag_vfs uv;
+
+       if (len < sizeof(uv))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &uv))
+               return true;
+
+       tprints("{udiag_vfs_dev=");
+       print_dev_t(uv.udiag_vfs_dev);
+       PRINT_FIELD_U(", ", uv, udiag_vfs_ino);
+       tprints("}");
+
+       return true;
+}
+
+static bool
+print_inode(struct tcb *const tcp,
+           void *const elem_buf,
+           const size_t elem_size,
+           void *const opaque_data)
+{
+       tprintf("%" PRIu32, *(uint32_t *) elem_buf);
+
+       return true;
+}
+
+static bool
+decode_unix_diag_inode(struct tcb *const tcp,
+                      const kernel_ulong_t addr,
+                      const kernel_ulong_t len,
+                      const void *const opaque_data)
+{
+       uint32_t inode;
+       const size_t nmemb = len / sizeof(inode);
+
+       if (!nmemb)
+               return false;
+
+       print_array(tcp, addr, nmemb, &inode, sizeof(inode),
+                   umoven_or_printaddr, print_inode, 0);
+
+       return true;
+}
+
+static bool
+decode_unix_diag_rqlen(struct tcb *const tcp,
+                      const kernel_ulong_t addr,
+                      const kernel_ulong_t len,
+                      const void *const opaque_data)
+{
+       struct unix_diag_rqlen rql;
+
+       if (len < sizeof(rql))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &rql))
+               return true;
+
+       PRINT_FIELD_U("{", rql, udiag_rqueue);
+       PRINT_FIELD_U(", ", rql, udiag_wqueue);
+       tprints("}");
+
+       return true;
+}
+
+static const nla_decoder_t unix_diag_msg_nla_decoders[] = {
+       [UNIX_DIAG_NAME]        = decode_nla_str,
+       [UNIX_DIAG_VFS]         = decode_unix_diag_vfs,
+       [UNIX_DIAG_PEER]        = decode_nla_u32,
+       [UNIX_DIAG_ICONS]       = decode_unix_diag_inode,
+       [UNIX_DIAG_RQLEN]       = decode_unix_diag_rqlen,
+       [UNIX_DIAG_MEMINFO]     = decode_meminfo,
+       [UNIX_DIAG_SHUTDOWN]    = decode_nla_u8
+};
+
 static void
 decode_unix_diag_msg(struct tcb *const tcp,
                     const struct nlmsghdr *const nlmsghdr,
@@ -160,7 +254,9 @@ decode_unix_diag_msg(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             unix_diag_attrs, "UNIX_DIAG_???");
+                             unix_diag_attrs, "UNIX_DIAG_???",
+                             unix_diag_msg_nla_decoders,
+                             ARRAY_SIZE(unix_diag_msg_nla_decoders), NULL);
        }
 }
 
@@ -197,6 +293,88 @@ decode_netlink_diag_req(struct tcb *const tcp,
        tprints("}");
 }
 
+static bool
+print_group(struct tcb *const tcp,
+           void *const elem_buf,
+           const size_t elem_size,
+           void *const opaque_data)
+{
+       if (elem_size < sizeof(kernel_ulong_t))
+               tprintf("%#0*x", (int) elem_size * 2 + 2,
+                       *(unsigned int *) elem_buf);
+       else
+               tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
+                       *(kernel_ulong_t *) elem_buf);
+
+       return true;
+}
+
+static bool
+decode_netlink_diag_groups(struct tcb *const tcp,
+                          const kernel_ulong_t addr,
+                          const kernel_ulong_t len,
+                          const void *const opaque_data)
+{
+       kernel_ulong_t buf;
+       const size_t nmemb = len / current_wordsize;
+
+       if (!nmemb)
+               return false;
+
+       print_array(tcp, addr, nmemb, &buf, current_wordsize,
+                   umoven_or_printaddr, print_group, 0);
+
+       return true;
+}
+
+static bool
+decode_netlink_diag_ring(struct tcb *const tcp,
+                        const kernel_ulong_t addr,
+                        const kernel_ulong_t len,
+                        const void *const opaque_data)
+{
+       struct netlink_diag_ring ndr;
+
+       if (len < sizeof(ndr))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &ndr))
+               return true;
+
+       PRINT_FIELD_U("{", ndr, ndr_block_size);
+       PRINT_FIELD_U(", ", ndr, ndr_block_nr);
+       PRINT_FIELD_U(", ", ndr, ndr_frame_size);
+       PRINT_FIELD_U(", ", ndr, ndr_frame_nr);
+       tprints("}");
+
+       return true;
+}
+
+static bool
+decode_netlink_diag_flags(struct tcb *const tcp,
+                         const kernel_ulong_t addr,
+                         const kernel_ulong_t len,
+                         const void *const opaque_data)
+{
+       uint32_t flags;
+
+       if (len < sizeof(flags))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &flags))
+               return true;
+
+       printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
+
+       return true;
+}
+
+static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
+       [NETLINK_DIAG_MEMINFO]  = decode_meminfo,
+       [NETLINK_DIAG_GROUPS]   = decode_netlink_diag_groups,
+       [NETLINK_DIAG_RX_RING]  = decode_netlink_diag_ring,
+       [NETLINK_DIAG_TX_RING]  = decode_netlink_diag_ring,
+       [NETLINK_DIAG_FLAGS]    = decode_netlink_diag_flags
+};
+
 static void
 decode_netlink_diag_msg(struct tcb *const tcp,
                        const struct nlmsghdr *const nlmsghdr,
@@ -235,7 +413,9 @@ decode_netlink_diag_msg(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             netlink_diag_attrs, "NETLINK_DIAG_???");
+                             netlink_diag_attrs, "NETLINK_DIAG_???",
+                             netlink_diag_msg_nla_decoders,
+                             ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
        }
 }
 
@@ -299,7 +479,8 @@ decode_packet_diag_msg(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             packet_diag_attrs, "PACKET_DIAG_???");
+                             packet_diag_attrs, "PACKET_DIAG_???",
+                             NULL, 0, NULL);
        }
 }
 
@@ -316,7 +497,9 @@ print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
        print_inet_addr(family, id->idiag_dst,
                        sizeof(id->idiag_dst), "idiag_dst");
 
-       PRINT_FIELD_U(", ", *id, idiag_if);
+       tprints(", idiag_if=");
+       print_ifindex(id->idiag_if);
+
        PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
 
        tprints("}");
@@ -359,7 +542,8 @@ decode_inet_diag_req_compat(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             inet_diag_req_attrs, "INET_DIAG_REQ_???");
+                             inet_diag_req_attrs, "INET_DIAG_REQ_???",
+                             NULL, 0, NULL);
        }
 }
 
@@ -399,7 +583,8 @@ decode_inet_diag_req_v2(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             inet_diag_req_attrs, "INET_DIAG_REQ_???");
+                             inet_diag_req_attrs, "INET_DIAG_REQ_???",
+                             NULL, 0, NULL);
        }
 }
 
@@ -419,6 +604,115 @@ decode_inet_diag_req(struct tcb *const tcp,
                                               family, addr, len);
 }
 
+static bool
+decode_inet_diag_meminfo(struct tcb *const tcp,
+                        const kernel_ulong_t addr,
+                        const kernel_ulong_t len,
+                        const void *const opaque_data)
+{
+       struct inet_diag_meminfo minfo;
+
+       if (len < sizeof(minfo))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &minfo))
+               return true;
+
+       PRINT_FIELD_U("{", minfo, idiag_rmem);
+       PRINT_FIELD_U(", ", minfo, idiag_wmem);
+       PRINT_FIELD_U(", ", minfo, idiag_fmem);
+       PRINT_FIELD_U(", ", minfo, idiag_tmem);
+       tprints("}");
+
+       return true;
+}
+
+static bool
+decode_tcpvegas_info(struct tcb *const tcp,
+                    const kernel_ulong_t addr,
+                    const kernel_ulong_t len,
+                    const void *const opaque_data)
+{
+       struct tcpvegas_info vegas;
+
+       if (len < sizeof(vegas))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &vegas))
+               return true;
+
+       PRINT_FIELD_U("{", vegas, tcpv_enabled);
+       PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
+       PRINT_FIELD_U(", ", vegas, tcpv_rtt);
+       PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
+       tprints("}");
+
+       return true;
+}
+
+static bool
+decode_tcp_dctcp_info(struct tcb *const tcp,
+                     const kernel_ulong_t addr,
+                     const kernel_ulong_t len,
+                     const void *const opaque_data)
+{
+       struct tcp_dctcp_info dctcp;
+
+       if (len < sizeof(dctcp))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &dctcp))
+               return true;
+
+       PRINT_FIELD_U("{", dctcp, dctcp_enabled);
+       PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
+       PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
+       PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
+       PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
+       tprints("}");
+
+       return true;
+}
+
+static bool
+decode_tcp_bbr_info(struct tcb *const tcp,
+                   const kernel_ulong_t addr,
+                   const kernel_ulong_t len,
+                   const void *const opaque_data)
+{
+       struct tcp_bbr_info bbr;
+
+       if (len < sizeof(bbr))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &bbr))
+               return true;
+
+       PRINT_FIELD_X("{", bbr, bbr_bw_lo);
+       PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
+       PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
+       PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
+       PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
+       tprints("}");
+
+       return true;
+}
+
+static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
+       [INET_DIAG_MEMINFO]     = decode_inet_diag_meminfo,
+       [INET_DIAG_INFO]        = NULL,                 /* unimplemented */
+       [INET_DIAG_VEGASINFO]   = decode_tcpvegas_info,
+       [INET_DIAG_CONG]        = decode_nla_str,
+       [INET_DIAG_TOS]         = decode_nla_u8,
+       [INET_DIAG_TCLASS]      = decode_nla_u8,
+       [INET_DIAG_SKMEMINFO]   = decode_meminfo,
+       [INET_DIAG_SHUTDOWN]    = decode_nla_u8,
+       [INET_DIAG_DCTCPINFO]   = decode_tcp_dctcp_info,
+       [INET_DIAG_PROTOCOL]    = decode_nla_u8,
+       [INET_DIAG_SKV6ONLY]    = decode_nla_u8,
+       [INET_DIAG_LOCALS]      = NULL,                 /* unimplemented */
+       [INET_DIAG_PEERS]       = NULL,                 /* unimplemented */
+       [INET_DIAG_PAD]         = NULL,
+       [INET_DIAG_MARK]        = decode_nla_u32,
+       [INET_DIAG_BBRINFO]     = decode_tcp_bbr_info
+};
+
 static void
 decode_inet_diag_msg(struct tcb *const tcp,
                     const struct nlmsghdr *const nlmsghdr,
@@ -457,7 +751,9 @@ decode_inet_diag_msg(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             inet_diag_attrs, "INET_DIAG_???");
+                             inet_diag_attrs, "INET_DIAG_???",
+                             inet_diag_msg_nla_decoders,
+                             ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);
        }
 }
 
@@ -532,7 +828,8 @@ decode_smc_diag_msg(struct tcb *const tcp,
        if (decode_nla && len > offset) {
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
-                             smc_diag_attrs, "SMC_DIAG_???");
+                             smc_diag_attrs, "SMC_DIAG_???",
+                             NULL, 0, NULL);
        }
 }
 #endif