From 106731a96c3f6abdbe1eabf5fca3e0f3e0e03fc8 Mon Sep 17 00:00:00 2001 From: Chen Jingpiao <chenjingpiao@gmail.com> Date: Thu, 8 Mar 2018 22:53:44 +0800 Subject: [PATCH] netlink: introduce NETLINK_NETFILTER parser * netlink_netfilter.c: New file. * Makefile.am (strace_SOURCES): Add it. * defs.h (decode_netlink_netfilter): New prototype. * netlink.c (netlink_decoders): Add NETLINK_NETFILTER. * xlat/netfilter_versions.in: New file. --- Makefile.am | 1 + defs.h | 1 + netlink.c | 3 ++ netlink_netfilter.c | 90 ++++++++++++++++++++++++++++++++++++++ xlat/netfilter_versions.in | 2 + 5 files changed, 97 insertions(+) create mode 100644 netlink_netfilter.c create mode 100644 xlat/netfilter_versions.in diff --git a/Makefile.am b/Makefile.am index 3bc546d1..181a0f8e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -202,6 +202,7 @@ strace_SOURCES = \ netlink_crypto.c \ netlink_sock_diag.h \ netlink_inet_diag.c \ + netlink_netfilter.c \ netlink_netlink_diag.c \ netlink_packet_diag.c \ netlink_route.c \ diff --git a/defs.h b/defs.h index 910edc3b..0597ddec 100644 --- a/defs.h +++ b/defs.h @@ -717,6 +717,7 @@ decode_netlink_ ## name(struct tcb *, const struct nlmsghdr *, \ /* End of DECL_NETLINK definition. */ DECL_NETLINK(crypto); +DECL_NETLINK(netfilter); DECL_NETLINK(route); DECL_NETLINK(selinux); DECL_NETLINK(sock_diag); diff --git a/netlink.c b/netlink.c index beb6ea4a..f5fa1f13 100644 --- a/netlink.c +++ b/netlink.c @@ -548,6 +548,9 @@ decode_nlmsgerr(struct tcb *const tcp, static const netlink_decoder_t netlink_decoders[] = { #ifdef HAVE_LINUX_CRYPTOUSER_H [NETLINK_CRYPTO] = decode_netlink_crypto, +#endif +#ifdef HAVE_LINUX_NETFILTER_NFNETLINK_H + [NETLINK_NETFILTER] = decode_netlink_netfilter, #endif [NETLINK_ROUTE] = decode_netlink_route, [NETLINK_SELINUX] = decode_netlink_selinux, diff --git a/netlink_netfilter.c b/netlink_netfilter.c new file mode 100644 index 00000000..a6028a1e --- /dev/null +++ b/netlink_netfilter.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018 Chen Jingpiao <chenjingpiao@gmail.com> + * Copyright (c) 2018 The strace developers. + * 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" + +#ifdef HAVE_LINUX_NETFILTER_NFNETLINK_H + +# include "print_fields.h" + +# include <netinet/in.h> +# include <arpa/inet.h> +# include "netlink.h" +# include <linux/netfilter/nfnetlink.h> + +# include "xlat/netfilter_versions.h" +# include "xlat/nl_netfilter_subsys_ids.h" + +bool +decode_netlink_netfilter(struct tcb *const tcp, + const struct nlmsghdr *const nlmsghdr, + const kernel_ulong_t addr, + const unsigned int len) +{ + if (nlmsghdr->nlmsg_type == NLMSG_DONE) + return false; + + struct nfgenmsg nfmsg; + + if (len < sizeof(nfmsg)) + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + else if (!umove_or_printaddr(tcp, addr, &nfmsg)) { + const uint8_t subsys_id = (uint8_t) (nlmsghdr->nlmsg_type >> 8); + uint16_t res_id = ntohs(nfmsg.res_id); + + PRINT_FIELD_XVAL("{", nfmsg, nfgen_family, addrfams, "AF_???"); + PRINT_FIELD_XVAL(", ", nfmsg, version, netfilter_versions, + "NFNETLINK_???"); + + /* + * Work around wrong endianness in res_id field, + * see linux commit v4.3-rc1~28^2~47^2~1 + */ + tprints(", res_id="); + if (subsys_id == NFNL_SUBSYS_NFTABLES + && res_id == NFNL_SUBSYS_NFTABLES) { + tprints("htons(NFNL_SUBSYS_NFTABLES)"); + } else if (subsys_id == NFNL_SUBSYS_NFTABLES + && nfmsg.res_id == NFNL_SUBSYS_NFTABLES) { + tprints("NFNL_SUBSYS_NFTABLES"); + } else { + tprintf("htons(%d)", res_id); + } + + const size_t offset = NLMSG_ALIGN(sizeof(nfmsg)); + if (len > offset) { + tprints(", "); + printstr_ex(tcp, addr + offset, + len - offset, QUOTE_FORCE_HEX); + } + } + + return true; +} + +#endif /* HAVE_LINUX_NETFILTER_NFNETLINK_H */ diff --git a/xlat/netfilter_versions.in b/xlat/netfilter_versions.in new file mode 100644 index 00000000..09afc8e9 --- /dev/null +++ b/xlat/netfilter_versions.in @@ -0,0 +1,2 @@ +NFNETLINK_V0 0 +NFNETLINK_V1 1