This commit introduces a general socket netlink parser which prints the header and a string for the remaining part of the buffer. It doesn't handle all the netlink flags and types because the parser needs more information. It will be done soon.
* net.c (printsock): Return family. (do_msghdr): Call decode_netlink_iov(). (send, sendto, recv, recvfrom): Call printsockbuf(). * netlink.c: New file. (decode_netlink): New function. * defs.h (decode_netlink, getfdproto): Add. (printsock): Change return type. (iov_decoder): Add IOV_DECODER_NETLINK. * io.c (print_iovec): Call decode_netlink(). * util.c (getfdproto): Remove the static keyword to the function. * Makefile.am (strace_SOURCES): Add netlink.c. * xlat/netlink_flags.in: New file. * xlat/netlink_types.in: New file. --- Makefile.am | 1 + defs.h | 7 ++++-- io.c | 5 ++++ net.c | 48 +++++++++++++++++++++++++++++--------- netlink.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 2 +- xlat/netlink_flags.in | 6 +++++ xlat/netlink_types.in | 4 ++++ 8 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 netlink.c create mode 100644 xlat/netlink_flags.in create mode 100644 xlat/netlink_types.in diff --git a/Makefile.am b/Makefile.am index 77e0cc8..ab0e200 100644 --- a/Makefile.am +++ b/Makefile.am @@ -156,6 +156,7 @@ strace_SOURCES = \ mtd.c \ native_defs.h \ net.c \ + netlink.c \ numa.c \ open.c \ or1k_atomic.c \ diff --git a/defs.h b/defs.h index a86c78c..cbd8c33 100644 --- a/defs.h +++ b/defs.h @@ -444,7 +444,8 @@ extern enum sock_proto get_proto_by_name(const char *); enum iov_decoder { IOV_DECODER_ADDR, - IOV_DECODER_STR + IOV_DECODER_STR, + IOV_DECODER_NETLINK }; typedef enum { @@ -557,6 +558,7 @@ extern const char *signame(const int); extern void pathtrace_select(const char *); extern int pathtrace_match(struct tcb *); extern int getfdpath(struct tcb *, int, char *, unsigned); +extern enum sock_proto getfdproto(struct tcb *, int); extern const char *xlookup(const struct xlat *, const uint64_t); extern const char *xlat_search(const struct xlat *, const size_t, const uint64_t); @@ -649,7 +651,7 @@ extern void printfd(struct tcb *, int); extern bool print_sockaddr_by_inode(const unsigned long, const enum sock_proto); extern bool print_sockaddr_by_inode_cached(const unsigned long); extern void print_dirfd(struct tcb *, int); -extern void printsock(struct tcb *, long, int); +extern int printsock(struct tcb *, long, int); extern void print_sock_optmgmt(struct tcb *, long, int); #ifdef ALPHA extern void printrusage32(struct tcb *, long); @@ -667,6 +669,7 @@ extern void printsignal(int); extern void tprint_iov(struct tcb *, unsigned long, unsigned long, enum iov_decoder); extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, enum iov_decoder, unsigned long); +extern void decode_netlink(struct tcb *, unsigned long, unsigned long); extern void tprint_open_modes(unsigned int); extern const char *sprint_open_modes(unsigned int); extern void print_seccomp_filter(struct tcb *, unsigned long); diff --git a/io.c b/io.c index ad92d84..ed66517 100644 --- a/io.c +++ b/io.c @@ -89,6 +89,11 @@ print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) printstr(tcp, iov[0], len); break; } + case IOV_DECODER_NETLINK: + { + decode_netlink(tcp, iov[0], iov[1]); + break; + } default: { printaddr(iov[0]); diff --git a/net.c b/net.c index e088477..97011d7 100644 --- a/net.c +++ b/net.c @@ -258,14 +258,14 @@ print_sockaddr(struct tcb *tcp, const sockaddr_buf_t *addr, const int addrlen) tprints("}"); } -void +int printsock(struct tcb *tcp, long addr, int addrlen) { sockaddr_buf_t addrbuf; if (addrlen < 2) { printaddr(addr); - return; + return -1; } if (addrlen > (int) sizeof(addrbuf)) @@ -273,10 +273,24 @@ printsock(struct tcb *tcp, long addr, int addrlen) memset(&addrbuf, 0, sizeof(addrbuf)); if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad)) - return; + return -1; addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0'; print_sockaddr(tcp, &addrbuf, addrlen); + + return addrbuf.sa.sa_family; +} + +static void +printsockbuf(struct tcb *tcp, int fd, long addr, long addrlen) +{ + switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) { + case SOCK_PROTO_NETLINK: + decode_netlink(tcp, addr, addrlen); + break; + default: + printstr(tcp, addr, addrlen); + } } #include "xlat/scmvals.h" @@ -576,13 +590,21 @@ printcmsghdr(struct tcb *tcp, unsigned long addr, size_t len) static void do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size) { + int family; + enum iov_decoder decoder; + tprintf("{msg_name(%d)=", msg->msg_namelen); - printsock(tcp, (long)msg->msg_name, msg->msg_namelen); + family = printsock(tcp, (long)msg->msg_name, msg->msg_namelen); tprintf(", msg_iov(%lu)=", (unsigned long)msg->msg_iovlen); + if (family == AF_NETLINK) + decoder = IOV_DECODER_NETLINK; + else + decoder = IOV_DECODER_STR; + tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen, - (unsigned long)msg->msg_iov, IOV_DECODER_STR, data_size); + (unsigned long)msg->msg_iov, decoder, data_size); #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen); @@ -865,7 +887,7 @@ SYS_FUNC(send) { printfd(tcp, tcp->u_arg[0]); tprints(", "); - printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); + printsockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); tprintf(", %lu, ", tcp->u_arg[2]); /* flags */ printflags(msg_flags, tcp->u_arg[3], "MSG_???"); @@ -877,7 +899,7 @@ SYS_FUNC(sendto) { printfd(tcp, tcp->u_arg[0]); tprints(", "); - printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); + printsockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); tprintf(", %lu, ", tcp->u_arg[2]); /* flags */ printflags(msg_flags, tcp->u_arg[3], "MSG_???"); @@ -926,10 +948,12 @@ SYS_FUNC(recv) printfd(tcp, tcp->u_arg[0]); tprints(", "); } else { - if (syserror(tcp)) + if (syserror(tcp)) { printaddr(tcp->u_arg[1]); - else - printstr(tcp, tcp->u_arg[1], tcp->u_rval); + } else { + printsockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], + tcp->u_rval); + } tprintf(", %lu, ", tcp->u_arg[2]); printflags(msg_flags, tcp->u_arg[3], "MSG_???"); @@ -945,11 +969,13 @@ SYS_FUNC(recvfrom) printfd(tcp, tcp->u_arg[0]); tprints(", "); } else { + /* buf */ if (syserror(tcp)) { printaddr(tcp->u_arg[1]); } else { - printstr(tcp, tcp->u_arg[1], tcp->u_rval); + printsockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], + tcp->u_rval); } /* len */ tprintf(", %lu, ", tcp->u_arg[2]); diff --git a/netlink.c b/netlink.c new file mode 100644 index 0000000..c43f6e7 --- /dev/null +++ b/netlink.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 Fabien Siron <fabien.si...@epita.fr> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defs.h" +#include <sys/socket.h> +#include <linux/netlink.h> +#include "xlat/netlink_flags.h" +#include "xlat/netlink_types.h" + +void +decode_netlink(struct tcb *tcp, unsigned long addr, unsigned long size) +{ + struct nlmsghdr nlmsghdr; + + if (size < sizeof(struct nlmsghdr)) { + printstr(tcp, addr, size); + return; + } + if (umove_or_printaddr(tcp, addr, &nlmsghdr)) + return; + + tprintf("{{len=%u, type=", nlmsghdr.nlmsg_len); + + printxval(netlink_types, nlmsghdr.nlmsg_type, "NLMSG_???"); + + tprints(", flags="); + printflags(netlink_flags, nlmsghdr.nlmsg_flags, "NLM_F_???"); + /* manage get/new requests */ + + tprintf(", seq=%u, pid=%u}", nlmsghdr.nlmsg_seq, + nlmsghdr.nlmsg_pid); + + if (size - sizeof(struct nlmsghdr) > 0) { + tprints(", "); + printstr(tcp, addr + sizeof(struct nlmsghdr), + size - sizeof(struct nlmsghdr)); + } + + tprints("}"); +} diff --git a/util.c b/util.c index d6956bc..c3bcaba 100644 --- a/util.c +++ b/util.c @@ -472,7 +472,7 @@ sprinttime(time_t t) return buf; } -static enum sock_proto +enum sock_proto getfdproto(struct tcb *tcp, int fd) { #ifdef HAVE_SYS_XATTR_H diff --git a/xlat/netlink_flags.in b/xlat/netlink_flags.in new file mode 100644 index 0000000..1354506 --- /dev/null +++ b/xlat/netlink_flags.in @@ -0,0 +1,6 @@ +NLM_F_REQUEST 0x1 +NLM_F_MULTI 0x2 +NLM_F_ACK 0x4 +NLM_F_ECHO 0x8 +NLM_F_DUMP_INTR 0x10 +NLM_F_DUMP_FILTERED 0x20 diff --git a/xlat/netlink_types.in b/xlat/netlink_types.in new file mode 100644 index 0000000..05eb076 --- /dev/null +++ b/xlat/netlink_types.in @@ -0,0 +1,4 @@ +NLMSG_NOOP 0x1 +NLMSG_ERROR 0x2 +NLMSG_DONE 0x3 +NLMSG_OVERRUN 0x4 -- 2.8.3 ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohomanageengine _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel