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. (_decode_netlink): New static function. (decode_iov_netlink): New function. * defs.h (decode_netlink, decode_netlink_iov, getfdproto): Add. (printsock): Change return type. * 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 | 5 ++- net.c | 55 ++++++++++++++++++++++++------- netlink.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 2 +- xlat/netlink_flags.in | 6 ++++ xlat/netlink_types.in | 4 +++ 7 files changed, 149 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 ab06921..ee35dab 100644 --- a/defs.h +++ b/defs.h @@ -552,6 +552,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); @@ -644,7 +645,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); @@ -661,6 +662,8 @@ extern const char *sprintsigmask_n(const char *, const void *, unsigned int); extern void printsignal(int); extern void tprint_iov(struct tcb *, unsigned long, unsigned long, int decode_iov); extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, int decode_iov, unsigned long); +extern void decode_netlink_iov(struct tcb *, unsigned long, unsigned long, 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/net.c b/net.c index 8cc97da..b1251f6 100644 --- a/net.c +++ b/net.c @@ -276,14 +276,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)) @@ -291,10 +291,30 @@ 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) +{ + enum sock_proto proto; + if (show_fd_path > 1) + proto = getfdproto(tcp, fd); + else + proto = SOCK_PROTO_UNKNOWN; + + switch (proto) { + case SOCK_PROTO_NETLINK: + decode_netlink(tcp, addr, addrlen); + break; + default: + printstr(tcp, addr, addrlen); + } } #include "xlat/scmvals.h" @@ -594,12 +614,20 @@ 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; + 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); - tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen, - (unsigned long)msg->msg_iov, 1, data_size); +#ifdef AF_NETLINK + if (family == AF_NETLINK) + decode_netlink_iov(tcp, (unsigned long) msg->msg_iovlen, + (unsigned long) msg->msg_iov, data_size); + else +#endif + tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen, + (unsigned long)msg->msg_iov, 1, data_size); #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen); @@ -886,7 +914,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_???"); @@ -898,7 +926,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_???"); @@ -947,10 +975,11 @@ 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_???"); @@ -966,11 +995,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..30116dd --- /dev/null +++ b/netlink.c @@ -0,0 +1,90 @@ +/* + * 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)) { + printaddr((unsigned long)addr); + return; + } + if (umove_or_printaddr(tcp, (unsigned long)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, (unsigned long)addr + sizeof(struct nlmsghdr), + size - sizeof(struct nlmsghdr)); + } + + tprints("}"); +} + +static bool +_decode_netlink(struct tcb *tcp, void *elem_buf, size_t elem_size, + void *opaque_data) { + const unsigned long *iov; + unsigned long addr, size; + + iov = elem_buf; + + addr = iov[0]; + size = iov[1]; + + decode_netlink(tcp, addr, size); + + return true; +} + +void +decode_netlink_iov(struct tcb *tcp, unsigned long len, unsigned long addr, + unsigned long data_size) +{ + unsigned long iov[2]; + + print_array(tcp, addr, len, iov, current_wordsize * 2, + umoven_or_printaddr, _decode_netlink, 0); +} 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://pubads.g.doubleclick.net/gampad/clk?id=1444514421&iu=/41014381 _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel