* 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 and AF_INET6; * xlat/inet_diag_extended_flags.in: New file.
Co-authored-by: Fabien Siron <fabien.si...@epita.fr> --- defs.h | 1 + linux/inet_diag.h | 33 +++++++- netlink_sock_diag.c | 179 +++++++++++++++++++++++++++++++++++++++ xlat/inet_diag_extended_flags.in | 16 ++++ 4 files changed, 228 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..245e476 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 91749dd..66f36b3 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" @@ -267,6 +271,179 @@ 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)); + + int text_size; + const char *name; + + if (family == AF_INET) { + text_size = INET_ADDRSTRLEN; + name = "AF_INET"; + } + else if (family == AF_INET6) { + text_size = INET6_ADDRSTRLEN; + name = "AF_INET6"; + } + else + text_size = 0; + + char buf[text_size]; + + + tprints(", "); + if (text_size + && inet_ntop(family, id->idiag_src, buf, text_size)) + tprintf("inet_pton(%s, \"%s\", idiag_src)", name, buf); + else + print_quoted_string((char *) id->idiag_src, + sizeof(id->idiag_src), 0); + + tprints(", "); + if (text_size + && inet_ntop(family, id->idiag_dst, buf, text_size)) + tprintf("inet_pton(%s, \"%s\", idiag_dst)", name, buf); + else + print_quoted_string((char *) id->idiag_dst, + sizeof(id->idiag_dst), 0); + + 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<<(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); + } + } else + tprints("..."); + tprints("}"); +} + +static void +decode_inet_diag_req_v2(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_v2 req = { .sdiag_family = family }; + const size_t offset = sizeof(req.sdiag_family); + + tprints("{sdiag_family="); + printxval(addrfams, req.sdiag_family, "AF_???"); + + tprints(", "); + if (len >= 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<<(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); + } + } else + tprints("..."); + tprints("}"); +} + +static void +decode_inet_diag_req(struct tcb *const tcp, + const struct nlmsghdr *const nlmsghdr, + const uint8_t family, + 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, + 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 +453,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 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 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel