* 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

Reply via email to