* sizeof_struct_rtnl_link_ifmap.c: New file. * Makefile.am (strace_SOURCES): Add it. * configure.ac (AC_CHECK_HEADERS): Add linux/if_link.h. (AC_CHECK_TYPES): Check for struct rtnl_link_stats64 in linux/if_link.h. (AC_CHECK_MEMBERS): Check for rx_nohandler field in struct rtnl_link_stats and struct rtnl_link_stats64. * rtnl_link.c: Include <linux/if_arp.h> and <linux/if_link.h>. (decode_ifla_address, decode_rtnl_link_stats, decode_rtnl_link_ifmap, decode_rtnl_link_stats64, print_item_id, decode_ifla_phys_item_id): New functions. (decode_ifla_phys_item_id): New array. (decode_ifinfomsg): Use it. --- Makefile.am | 1 + configure.ac | 6 + rtnl_link.c | 259 +++++++++++++++++++++++++++++++++++++++- sizeof_struct_rtnl_link_ifmap.c | 44 +++++++ 4 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 sizeof_struct_rtnl_link_ifmap.c
diff --git a/Makefile.am b/Makefile.am index 2a477f6..cf34250 100644 --- a/Makefile.am +++ b/Makefile.am @@ -272,6 +272,7 @@ strace_SOURCES = \ sigevent.h \ signal.c \ signalfd.c \ + sizeof_struct_rtnl_link_ifmap.c \ sock.c \ sockaddr.c \ socketutils.c \ diff --git a/configure.ac b/configure.ac index cb398fb..dacd67f 100644 --- a/configure.ac +++ b/configure.ac @@ -382,6 +382,7 @@ AC_CHECK_HEADERS(m4_normalize([ linux/genetlink.h linux/hiddev.h linux/if_addr.h + linux/if_link.h linux/ip_vs.h linux/ipc.h linux/mmtimer.h @@ -447,6 +448,11 @@ AC_CHECK_TYPES([struct dcbmsg],,, [#include <linux/dcbnl.h>]) AC_CHECK_TYPES([struct ifaddrlblmsg],,, [#include <linux/if_addrlabel.h>]) AC_CHECK_TYPES([struct netconfmsg],,, [#include <linux/netconf.h>]) +AC_CHECK_TYPES([struct rtnl_link_stats64], [ + AC_CHECK_MEMBERS([struct rtnl_link_stats64.rx_nohandler],,, [#include <linux/if_link.h>]) +],, [#include <linux/if_link.h>]) +AC_CHECK_MEMBERS([struct rtnl_link_stats.rx_nohandler],,, [#include <linux/if_link.h>]) + AC_CHECK_TYPES([struct statfs], [ AC_CHECK_MEMBERS([struct statfs.f_frsize],,, [#include <linux/types.h> #include <asm/statfs.h>]) diff --git a/rtnl_link.c b/rtnl_link.c index 18897f3..9fd79b2 100644 --- a/rtnl_link.c +++ b/rtnl_link.c @@ -32,11 +32,266 @@ #include "nlattr.h" #include "print_fields.h" +#include <arpa/inet.h> + +#include <linux/if_arp.h> +#ifdef HAVE_LINUX_IF_LINK_H +# include <linux/if_link.h> +#endif #include "netlink.h" #include <linux/rtnetlink.h> #include "xlat/rtnl_link_attrs.h" +static bool +decode_ifla_address(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + const struct ifinfomsg *const ifinfo = opaque_data; + union { + struct in_addr a4; + struct in6_addr a6; + } addrbuf; + int af; + size_t size = 0; + + switch (ifinfo->ifi_type) { + case ARPHRD_TUNNEL: + case ARPHRD_SIT: + case ARPHRD_IPGRE: + af = AF_INET; + size = sizeof(addrbuf.a4); + break; + case ARPHRD_TUNNEL6: + af = AF_INET6; + size = sizeof(addrbuf.a6); + break; + } + if (!size || len < size) { + size_t i; + uint8_t buf; + + for (i = 0; i < len; i++) { + if (i) + tprints(":"); + if (umove(tcp, addr + i, &buf) < 0) { + tprints("..."); + break; + } + tprintf("%02x", buf); + } + } else if (!umoven_or_printaddr(tcp, addr, size, &addrbuf)) { + char buf[INET6_ADDRSTRLEN]; + if (inet_ntop(af, &addrbuf, buf, sizeof(buf))) + tprintf("%s", buf); + else + return false; + } + + return true; +} + +static bool +decode_rtnl_link_stats(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + struct rtnl_link_stats st; + + if (len < sizeof(st)) + return false; + else if (!umove_or_printaddr(tcp, addr, &st)) { + PRINT_FIELD_U("{", st, rx_packets); + PRINT_FIELD_U(", ", st, tx_packets); + PRINT_FIELD_U(", ", st, rx_bytes); + PRINT_FIELD_U(", ", st, tx_bytes); + PRINT_FIELD_U(", ", st, rx_errors); + PRINT_FIELD_U(", ", st, tx_errors); + PRINT_FIELD_U(", ", st, rx_dropped); + PRINT_FIELD_U(", ", st, tx_dropped); + PRINT_FIELD_U(", ", st, multicast); + PRINT_FIELD_U(", ", st, collisions); + + PRINT_FIELD_U(", ", st, rx_length_errors); + PRINT_FIELD_U(", ", st, rx_over_errors); + PRINT_FIELD_U(", ", st, rx_crc_errors); + PRINT_FIELD_U(", ", st, rx_frame_errors); + PRINT_FIELD_U(", ", st, rx_fifo_errors); + PRINT_FIELD_U(", ", st, rx_missed_errors); + + PRINT_FIELD_U(", ", st, tx_aborted_errors); + PRINT_FIELD_U(", ", st, tx_carrier_errors); + PRINT_FIELD_U(", ", st, tx_fifo_errors); + PRINT_FIELD_U(", ", st, tx_heartbeat_errors); + PRINT_FIELD_U(", ", st, tx_window_errors); + + PRINT_FIELD_U(", ", st, rx_compressed); + PRINT_FIELD_U(", ", st, tx_compressed); +#ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER + PRINT_FIELD_U(", ", st, rx_nohandler); +#endif + tprints("}"); + } + + return true; +} + +static bool +decode_rtnl_link_ifmap(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + struct rtnl_link_ifmap map; + unsigned int sizeof_ifmap = sizeof_struct_rtnl_link_ifmap(); + + if (len < sizeof_ifmap) + return false; + else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) { + PRINT_FIELD_X("{", map, mem_start); + PRINT_FIELD_X(", ", map, mem_end); + PRINT_FIELD_X(", ", map, base_addr); + PRINT_FIELD_U(", ", map, irq); + PRINT_FIELD_U(", ", map, dma); + PRINT_FIELD_U(", ", map, port); + tprints("}"); + } + + return true; +} + +static bool +decode_rtnl_link_stats64(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ +#ifdef HAVE_STRUCT_RTNL_LINK_STATS64 + struct rtnl_link_stats64 st; + + if (len < sizeof(st)) + return false; + else if (!umove_or_printaddr(tcp, addr, &st)) { + PRINT_FIELD_U("{", st, rx_packets); + PRINT_FIELD_U(", ", st, tx_packets); + PRINT_FIELD_U(", ", st, rx_bytes); + PRINT_FIELD_U(", ", st, tx_bytes); + PRINT_FIELD_U(", ", st, rx_errors); + PRINT_FIELD_U(", ", st, tx_errors); + PRINT_FIELD_U(", ", st, rx_dropped); + PRINT_FIELD_U(", ", st, tx_dropped); + PRINT_FIELD_U(", ", st, multicast); + PRINT_FIELD_U(", ", st, collisions); + + PRINT_FIELD_U(", ", st, rx_length_errors); + PRINT_FIELD_U(", ", st, rx_over_errors); + PRINT_FIELD_U(", ", st, rx_crc_errors); + PRINT_FIELD_U(", ", st, rx_frame_errors); + PRINT_FIELD_U(", ", st, rx_fifo_errors); + PRINT_FIELD_U(", ", st, rx_missed_errors); + + PRINT_FIELD_U(", ", st, tx_aborted_errors); + PRINT_FIELD_U(", ", st, tx_carrier_errors); + PRINT_FIELD_U(", ", st, tx_fifo_errors); + PRINT_FIELD_U(", ", st, tx_heartbeat_errors); + PRINT_FIELD_U(", ", st, tx_window_errors); + + PRINT_FIELD_U(", ", st, rx_compressed); + PRINT_FIELD_U(", ", st, tx_compressed); +#ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER + PRINT_FIELD_U(", ", st, rx_nohandler); +#endif + tprints("}"); + } + + return true; +#else + return false; +#endif +} + +static bool +print_item_id(struct tcb *const tcp, void *const elem_buf, + const size_t elem_size, void *const opaque_data) +{ + unsigned int *const count = opaque_data; + + /* MAX_PHYS_ITEM_ID_LEN = 32 */ + if ((*count)++ >= 32) { + tprints("..."); + return false; + } + + tprintf("%" PRIu8, *(uint8_t *) elem_buf); + + return true; +} + +static bool +decode_ifla_phys_item_id(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + uint8_t id; + unsigned int count = 0; + + print_array(tcp, addr, len, &id, sizeof(id), + umoven_or_printaddr, print_item_id, &count); + + return true; +} + +static const nla_decoder_t ifinfomsg_nla_decoders[] = { + [IFLA_ADDRESS] = decode_ifla_address, + [IFLA_BROADCAST] = decode_ifla_address, + [IFLA_IFNAME] = decode_nla_str, + [IFLA_MTU] = decode_nla_u32, + [IFLA_LINK] = decode_nla_u32, + [IFLA_QDISC] = decode_nla_str, + [IFLA_STATS] = decode_rtnl_link_stats, + [IFLA_COST] = NULL, + [IFLA_PRIORITY] = NULL, + [IFLA_MASTER] = decode_nla_u32, + [IFLA_WIRELESS] = NULL, + [IFLA_PROTINFO] = NULL, + [IFLA_TXQLEN] = decode_nla_u32, + [IFLA_MAP] = decode_rtnl_link_ifmap, + [IFLA_WEIGHT] = decode_nla_u32, + [IFLA_OPERSTATE] = decode_nla_u8, + [IFLA_LINKMODE] = decode_nla_u8, + [IFLA_LINKINFO] = NULL, + [IFLA_NET_NS_PID] = decode_nla_u32, + [IFLA_IFALIAS] = decode_nla_str, + [IFLA_NUM_VF] = decode_nla_u32, + [IFLA_VFINFO_LIST] = NULL, + [IFLA_STATS64] = decode_rtnl_link_stats64, + [IFLA_VF_PORTS] = NULL, + [IFLA_PORT_SELF] = NULL, + [IFLA_AF_SPEC] = NULL, + [IFLA_GROUP] = decode_nla_u32, + [IFLA_NET_NS_FD] = decode_nla_u32, + [IFLA_EXT_MASK] = decode_nla_u32, + [IFLA_PROMISCUITY] = decode_nla_u32, + [IFLA_NUM_TX_QUEUES] = decode_nla_u32, + [IFLA_NUM_RX_QUEUES] = decode_nla_u32, + [IFLA_CARRIER] = decode_nla_u8, + [IFLA_PHYS_PORT_ID] = decode_ifla_phys_item_id, + [IFLA_CARRIER_CHANGES] = decode_nla_u32, + [IFLA_PHYS_SWITCH_ID] = decode_ifla_phys_item_id, + [IFLA_LINK_NETNSID] = decode_nla_s32, + [IFLA_PHYS_PORT_NAME] = decode_nla_str, + [IFLA_PROTO_DOWN] = decode_nla_u8, + [IFLA_GSO_MAX_SEGS] = decode_nla_u32, + [IFLA_GSO_MAX_SIZE] = decode_nla_u32, + [IFLA_PAD] = NULL, + [IFLA_XDP] = NULL, + [IFLA_EVENT] = decode_nla_u32 +}; + DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg) { struct ifinfomsg ifinfo = { .ifi_family = family }; @@ -66,6 +321,8 @@ DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg) if (decode_nla && len > offset) { tprints(", "); decode_nlattr(tcp, addr + offset, len - offset, - rtnl_link_attrs, "IFLA_???", NULL, 0, NULL); + rtnl_link_attrs, "IFLA_???", + ifinfomsg_nla_decoders, + ARRAY_SIZE(ifinfomsg_nla_decoders), &ifinfo); } } diff --git a/sizeof_struct_rtnl_link_ifmap.c b/sizeof_struct_rtnl_link_ifmap.c new file mode 100644 index 0000000..aba08db --- /dev/null +++ b/sizeof_struct_rtnl_link_ifmap.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 JingPiao Chen <chenjingp...@gmail.com> + * Copyright (c) 2017 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_IF_LINK_H +# include <linux/if_link.h> +#endif +#include "netlink.h" +#include <linux/rtnetlink.h> + +#include DEF_MPERS_TYPE(struct_rtnl_link_ifmap) +typedef struct rtnl_link_ifmap struct_rtnl_link_ifmap; +#include MPERS_DEFS + +MPERS_PRINTER_DECL(unsigned int, sizeof_struct_rtnl_link_ifmap, void) +{ + return sizeof(struct_rtnl_link_ifmap); +} -- 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