From 6fbbf72dcded31e0d5d06e4294b94a601cbba188 Mon Sep 17 00:00:00 2001 From: JingPiao Chen Date: Tue, 13 Jun 2017 12:43:31 +0800 Subject: [PATCH] netlink: add a basic socket diag parser of AF_INET and AF_INET6 messages * 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 , 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 and AF_INET6; * xlat/inet_diag_extended_flags.in: New file. Co-authored-by: Fabien Siron --- defs.h | 1 + linux/inet_diag.h | 33 ++++++- netlink_sock_diag.c | 153 +++++++++++++++++++++++++++++++ xlat/inet_diag_extended_flags.in | 17 ++++ 4 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 xlat/inet_diag_extended_flags.in diff --git a/defs.h b/defs.h index 9dbb6436..487e51bd 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 69012af0..245e4761 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,25 @@ 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, +}; + #endif /* !STRACE_LINUX_INET_DIAG_H */ diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c index 91749dd4..690a032a 100644 --- a/netlink_sock_diag.c +++ b/netlink_sock_diag.c @@ -30,11 +30,15 @@ #include "defs.h" #include +#include +#include #include #include #include #include +#include "xlat/inet_diag_extended_flags.h" + #include "xlat/tcp_states.h" #include "xlat/tcp_state_flags.h" @@ -267,6 +271,153 @@ decode_packet_diag_msg(struct tcb *const tcp, tprints("}"); } +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)); + + tprints(", "); + print_inet_addr(family, id->idiag_src, + sizeof(id->idiag_src), "idiag_src"); + tprints(", "); + print_inet_addr(family, id->idiag_dst, + sizeof(id->idiag_dst), "idiag_dst"); + + tprintf(", idiag_if=%" PRIu32 + ", idiag_cookie=[%" PRIu32 ", %" PRIu32 "]}", + id->idiag_if, id->idiag_cookie[0], id->idiag_cookie[1]); +} + +static void +decode_inet_diag_req_compat(struct tcb *const tcp, + const struct nlmsghdr *const nlmsghdr, + const uint8_t family, + const kernel_ulong_t addr, + const kernel_ulong_t len) +{ + struct inet_diag_req req = { .idiag_family = family }; + const size_t offset = sizeof(req.idiag_family); + + tprints("{idiag_family="); + printxval(addrfams, req.idiag_family, "AF_???"); + + tprints(", "); + if (len >= sizeof(req)) { + if (!umoven_or_printaddr(tcp, addr + offset, + sizeof(req) - offset, + (void *) &req + offset)) { + 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<= sizeof(req)) { + if (!umoven_or_printaddr(tcp, addr + offset, + sizeof(req) - offset, + (void *) &req + offset)) { + tprints("sdiag_protocol="); + printxval(inet_protocols, req.sdiag_protocol, + "IPPROTO_???"); + tprints(", idiag_ext="); + printflags(inet_diag_extended_flags, req.idiag_ext, + "1<nlmsg_type == TCPDIAG_GETSOCK + || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK) + return decode_inet_diag_req_compat(tcp, nlmsghdr, + family, addr, len); + else + return decode_inet_diag_req_v2(tcp, nlmsghdr, + family, addr, len); +} + +static void +decode_inet_diag_msg(struct tcb *const tcp, + const struct nlmsghdr *const nlmsghdr, + const uint8_t family, + const kernel_ulong_t addr, + const kernel_ulong_t len) +{ + struct inet_diag_msg msg = { .idiag_family = family }; + const size_t offset = sizeof(msg.idiag_family); + + tprints("{idiag_family="); + printxval(addrfams, msg.idiag_family, "AF_???"); + + tprints(", "); + if (len >= sizeof(msg)) { + if (!umoven_or_printaddr(tcp, addr + offset, + sizeof(msg) - offset, + (void *) &msg + offset)) { + 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); + } + } else + tprints("..."); + tprints("}"); +} + typedef void (*netlink_diag_decoder_t)(struct tcb *, const struct nlmsghdr *, uint8_t family, @@ -276,6 +427,8 @@ typedef void (*netlink_diag_decoder_t)(struct tcb *, static const struct { const netlink_diag_decoder_t request, response; } diag_decoders[] = { + [AF_INET] = { decode_inet_diag_req, decode_inet_diag_msg }, + [AF_INET6] = { 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 00000000..05be3ca4 --- /dev/null +++ b/xlat/inet_diag_extended_flags.in @@ -0,0 +1,17 @@ +#unconditional +1<<(INET_DIAG_MEMINFO-1) +1<<(INET_DIAG_INFO-1) +1<<(INET_DIAG_VEGASINFO-1) +1<<(INET_DIAG_CONG-1) +1<<(INET_DIAG_TOS-1) +1<<(INET_DIAG_TCLASS-1) +1<<(INET_DIAG_SKMEMINFO-1) +1<<(INET_DIAG_SHUTDOWN-1) +1<<(INET_DIAG_DCTCPINFO-1) +1<<(INET_DIAG_PROTOCOL-1) +1<<(INET_DIAG_SKV6ONLY-1) +1<<(INET_DIAG_LOCALS-1) +1<<(INET_DIAG_PEERS-1) +1<<(INET_DIAG_PAD-1) +1<<(INET_DIAG_MARK-1) +1<<(INET_DIAG_BBRINFO-1) -- 2.40.0