[PATCH 5/8] netlink: add a basic socket diag parser of AF_INET messages
JingPiao Chen
chenjingpiao at gmail.com
Tue Jun 13 14:13:22 UTC 2017
* defs.h (inet_protocols): New xlat prototype.
* linux/inet_diag.h (inet_diag_req): New structure.
(INET_DIAG_*): New enum.
* netlink_sock_diag.c: Include <arpa/inet.h>, <linux/inet_diag.h>
and "xlat/inet_diag_extended_flags.h".
(print_inet_diag_sockid, decode_inet_diag_req_compat)
(decode_inet_diag_req_v2, decode_inet_diag_req)
(decode_inet_diag_msg): New functions.
(diag_decoders): Add AF_INET.
* xlat/inet_diag_extended_flags.in: New file.
Co-authored-by: Fabien Siron <fabien.siron at epita.fr>
---
defs.h | 1 +
linux/inet_diag.h | 36 +++++++++++-
netlink_sock_diag.c | 122 +++++++++++++++++++++++++++++++++++++++
xlat/inet_diag_extended_flags.in | 16 +++++
4 files changed, 174 insertions(+), 1 deletion(-)
create mode 100644 xlat/inet_diag_extended_flags.in
diff --git a/defs.h b/defs.h
index f7d25f0..0b32b24 100644
--- a/defs.h
+++ b/defs.h
@@ -293,6 +293,7 @@ extern const struct xlat clocknames[];
extern const struct xlat dirent_types[];
extern const struct xlat ethernet_protocols[];
extern const struct xlat evdev_abs[];
+extern const struct xlat inet_protocols[];
extern const struct xlat msg_flags[];
extern const struct xlat netlink_protocols[];
extern const struct xlat open_access_modes[];
diff --git a/linux/inet_diag.h b/linux/inet_diag.h
index 69012af..7302c87 100644
--- a/linux/inet_diag.h
+++ b/linux/inet_diag.h
@@ -14,7 +14,17 @@ struct inet_diag_sockid {
uint32_t idiag_cookie[2];
};
-/* Request structure */
+/* Request structures */
+struct inet_diag_req {
+ uint8_t idiag_family;
+ uint8_t idiag_src_len;
+ uint8_t idiag_dst_len;
+ uint8_t idiag_ext;
+ struct inet_diag_sockid id;
+ uint32_t idiag_states;
+ uint32_t idiag_dbs;
+};
+
struct inet_diag_req_v2 {
uint8_t sdiag_family;
uint8_t sdiag_protocol;
@@ -40,4 +50,28 @@ struct inet_diag_msg {
uint32_t idiag_inode;
};
+/* Extensions */
+enum {
+ INET_DIAG_NONE,
+ INET_DIAG_MEMINFO,
+ INET_DIAG_INFO,
+ INET_DIAG_VEGASINFO,
+ INET_DIAG_CONG,
+ INET_DIAG_TOS,
+ INET_DIAG_TCLASS,
+ INET_DIAG_SKMEMINFO,
+ INET_DIAG_SHUTDOWN,
+ INET_DIAG_DCTCPINFO,
+ INET_DIAG_PROTOCOL, /* response attribute only */
+ INET_DIAG_SKV6ONLY,
+ INET_DIAG_LOCALS,
+ INET_DIAG_PEERS,
+ INET_DIAG_PAD,
+ INET_DIAG_MARK,
+ INET_DIAG_BBRINFO,
+ __INET_DIAG_MAX,
+};
+
+#define INET_DIAG_MAX (__INET_DIAG_MAX - 1)
+
#endif /* !STRACE_LINUX_INET_DIAG_H */
diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c
index 3f153a8..7467d1a 100644
--- a/netlink_sock_diag.c
+++ b/netlink_sock_diag.c
@@ -30,11 +30,15 @@
#include "defs.h"
#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <linux/inet_diag.h>
#include <linux/netlink.h>
#include <linux/netlink_diag.h>
#include <linux/packet_diag.h>
#include <linux/unix_diag.h>
+#include "xlat/inet_diag_extended_flags.h"
+
#include "xlat/tcp_states.h"
#include "xlat/tcp_state_flags.h"
@@ -210,9 +214,127 @@ decode_packet_diag_msg(struct tcb *const tcp,
return true;
}
+static void
+print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
+{
+ tprintf("{idiag_sport=htons(%u), idiag_dport=htons(%u)",
+ ntohs(id->idiag_sport), ntohs(id->idiag_dport));
+ int text_size = family == AF_INET ?
+ INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
+ char buf[text_size];
+
+ inet_ntop(family, id->idiag_src, buf, text_size);
+ tprintf(", inet_pton(%s, \"%s\", idiag_src)",
+ family == AF_INET ? "AF_INET" : "AF_INET6", buf);
+
+ inet_ntop(family, id->idiag_dst, buf, text_size);
+ tprintf(", inet_pton(%s, \"%s\", idiag_dst)",
+ family == AF_INET ? "AF_INET" : "AF_INET6", buf);
+
+ tprintf(", idiag_if=%" PRIu32 ", idiag_cookie=[%" PRIu32
+ ", %" PRIu32 "]}", id->idiag_if, id->idiag_cookie[0],
+ id->idiag_cookie[1]);
+}
+
+static bool
+decode_inet_diag_req_compat(struct tcb *const tcp,
+ const struct nlmsghdr *const nlmsghdr,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len)
+{
+ struct inet_diag_req req;
+
+ if (len < sizeof(req) || umove(tcp, addr, &req) < 0)
+ return false;
+
+ tprints("{idiag_family=");
+ printxval(addrfams, req.idiag_family, "AF_???");
+ tprintf(", idiag_src_len=%" PRIu8 ", idiag_dst_len=%" PRIu8,
+ req.idiag_src_len, req.idiag_dst_len);
+ tprints(", idiag_ext=");
+ printflags(inet_diag_extended_flags, req.idiag_ext,
+ "1<<(INET_DIAG_\?\?\?-1)");
+ tprints(", id=");
+ print_inet_diag_sockid(&req.id, req.idiag_family);
+ tprints(", idiag_states=");
+ printflags(tcp_state_flags, req.idiag_states, "1<<TCP_???");
+ tprintf(", idiag_dbs=%" PRIu32 "}", req.idiag_dbs);
+
+ return true;
+}
+
+static bool
+decode_inet_diag_req_v2(struct tcb *const tcp,
+ const struct nlmsghdr *const nlmsghdr,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len)
+{
+ struct inet_diag_req_v2 req;
+
+ if (len < sizeof(req) || umove(tcp, addr, &req) < 0)
+ return false;
+
+ tprints("{sdiag_family=");
+ printxval(addrfams, req.sdiag_family, "AF_???");
+ tprints(", sdiag_protocol=");
+ printxval(inet_protocols, req.sdiag_protocol, "IPPROTO_???");
+ tprints(", idiag_ext=");
+ printflags(inet_diag_extended_flags, req.idiag_ext,
+ "1<<(INET_DIAG_\?\?\?-1)");
+ tprints(", idiag_states=");
+ printflags(tcp_state_flags, req.idiag_states, "1<<TCP_???");
+ tprints(", id=");
+ print_inet_diag_sockid(&req.id, req.sdiag_family);
+ tprints("}");
+
+ return true;
+}
+
+static bool
+decode_inet_diag_req(struct tcb *const tcp,
+ const struct nlmsghdr *const nlmsghdr,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len)
+{
+ if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
+ || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
+ return decode_inet_diag_req_compat(tcp, nlmsghdr, addr, len);
+ else
+ return decode_inet_diag_req_v2(tcp, nlmsghdr, addr, len);
+}
+
+static bool
+decode_inet_diag_msg(struct tcb *const tcp,
+ const struct nlmsghdr *const nlmsghdr,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len)
+{
+ struct inet_diag_msg msg;
+
+ if (len < sizeof(msg) || umove(tcp, addr, &msg) < 0)
+ return false;
+
+ tprints("{idiag_family=");
+ printxval(addrfams, msg.idiag_family, "AF_???");
+ tprints(", idiag_state=");
+ printxval(tcp_states, msg.idiag_state, "TCP_???");
+ tprintf(", idiag_timer=%" PRIu8 ", idiag_retrans=%" PRIu8,
+ msg.idiag_timer, msg.idiag_retrans);
+ tprints(", id=");
+ print_inet_diag_sockid(&msg.id, msg.idiag_family);
+ tprintf(", idiag_expires=%" PRIu32 ", idiag_rqueue=%" PRIu32
+ ", idiag_wqueue=%" PRIu32 ", idiag_uid=%" PRIu32
+ ", idiag_inode=%" PRIu32 "}",
+ msg.idiag_expires, msg.idiag_rqueue, msg.idiag_wqueue,
+ msg.idiag_uid, msg.idiag_inode);
+
+ return true;
+}
+
static const struct {
const netlink_decoder_t request, response;
} diag_decoders[] = {
+ [AF_INET] = { decode_inet_diag_req, decode_inet_diag_msg },
[AF_NETLINK] = { decode_netlink_diag_req, decode_netlink_diag_msg },
[AF_PACKET] = { decode_packet_diag_req, decode_packet_diag_msg },
[AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg }
diff --git a/xlat/inet_diag_extended_flags.in b/xlat/inet_diag_extended_flags.in
new file mode 100644
index 0000000..2466696
--- /dev/null
+++ b/xlat/inet_diag_extended_flags.in
@@ -0,0 +1,16 @@
+{ 1<<(INET_DIAG_MEMINFO-1) , "(1<<(INET_DIAG_MEMINFO-1))" },
+{ 1<<(INET_DIAG_INFO-1) , "(1<<(INET_DIAG_INFO-1))" },
+{ 1<<(INET_DIAG_VEGASINFO-1) , "(1<<(INET_DIAG_VEGASINFO-1))" },
+{ 1<<(INET_DIAG_CONG-1) , "(1<<(INET_DIAG_CONG-1))" },
+{ 1<<(INET_DIAG_TOS-1) , "(1<<(INET_DIAG_TOS-1))" },
+{ 1<<(INET_DIAG_TCLASS-1) , "(1<<(INET_DIAG_TCLASS-1))" },
+{ 1<<(INET_DIAG_SKMEMINFO-1) , "(1<<(INET_DIAG_SKMEMINFO-1))" },
+{ 1<<(INET_DIAG_SHUTDOWN-1) , "(1<<(INET_DIAG_SHUTDOWN-1))" },
+{ 1<<(INET_DIAG_DCTCPINFO-1) , "(1<<(INET_DIAG_DCTCPINFO-1))" },
+{ 1<<(INET_DIAG_PROTOCOL-1) , "(1<<(INET_DIAG_PROTOCOL-1))" },
+{ 1<<(INET_DIAG_SKV6ONLY-1) , "(1<<(INET_DIAG_SKV6ONLY-1))" },
+{ 1<<(INET_DIAG_LOCALS-1) , "(1<<(INET_DIAG_LOCALS-1))" },
+{ 1<<(INET_DIAG_PEERS-1) , "(1<<(INET_DIAG_PEERS-1))" },
+{ 1<<(INET_DIAG_PAD-1) , "(1<<(INET_DIAG_PAD-1))" },
+{ 1<<(INET_DIAG_MARK-1) , "(1<<(INET_DIAG_MARK-1))" },
+{ 1<<(INET_DIAG_BBRINFO-1) , "(1<<(INET_DIAG_BBRINFO-1))" },
--
2.7.4
More information about the Strace-devel
mailing list