From: Vadim Kochan <vadi...@gmail.com>

Dump RTnetlink interface related info with attributes.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 netsniff-ng/Makefile |   2 +
 proto_nlmsg.c        | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 234 insertions(+)

diff --git a/netsniff-ng/Makefile b/netsniff-ng/Makefile
index 9fe2ffe..92990ff 100644
--- a/netsniff-ng/Makefile
+++ b/netsniff-ng/Makefile
@@ -1,5 +1,6 @@
 netsniff-ng-libs =     $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) 
$(PKG_CONFIG) --libs libnl-3.0) \
                        $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) 
$(PKG_CONFIG) --libs libnl-genl-3.0) \
+                       $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) 
$(PKG_CONFIG) --libs libnl-route-3.0) \
                        -lpthread
 
 ifeq ($(CONFIG_LIBPCAP), 1)
@@ -78,6 +79,7 @@ endif
 
 netsniff-ng-eflags = $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) 
--cflags libnl-3.0) \
                     $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) 
--cflags libnl-genl-3.0) \
+                    $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) 
--cflags libnl-route-3.0) \
                     -DNEED_TCPDUMP_LIKE_FILTER
 
 netsniff-ng-confs =    ether.conf \
diff --git a/proto_nlmsg.c b/proto_nlmsg.c
index 1b0eed7..c482df1 100644
--- a/proto_nlmsg.c
+++ b/proto_nlmsg.c
@@ -9,6 +9,9 @@
 #include <limits.h>
 #include <libgen.h>
 #include <netlink/msg.h>
+#include <netlink/route/link.h>
+#include <linux/if_arp.h>
+#include <arpa/inet.h>
 
 #include "pkt_buff.h"
 #include "proto.h"
@@ -120,6 +123,114 @@ static const char *nlmsg_rtnl_type2str(uint16_t type)
        }
 }
 
+static char *if_type2str(uint16_t type)
+{
+       switch (type) {
+       case ARPHRD_ETHER: return "ether";
+       case ARPHRD_EETHER: return "eether";
+       case ARPHRD_AX25: return "ax25";
+       case ARPHRD_PRONET: return "pronet";
+       case ARPHRD_CHAOS: return "chaos";
+       case ARPHRD_IEEE802: return "ieee802";
+       case ARPHRD_ARCNET: return "arcnet";
+       case ARPHRD_APPLETLK: return "appletlk";
+       case ARPHRD_DLCI: return "dlci";
+       case ARPHRD_ATM: return "atm";
+       case ARPHRD_METRICOM: return "metricom";
+       case ARPHRD_IEEE1394: return "ieee1394";
+       case ARPHRD_INFINIBAND: return "infiniband";
+       case ARPHRD_SLIP: return "slip";
+       case ARPHRD_CSLIP: return "cslip";
+       case ARPHRD_SLIP6: return "slip6";
+       case ARPHRD_CSLIP6: return "cslip6";
+       case ARPHRD_RSRVD: return "RSRVD";
+       case ARPHRD_ADAPT: return "adapt";
+       case ARPHRD_ROSE: return "rose";
+       case ARPHRD_X25: return "x25";
+       case ARPHRD_HWX25: return "hwx25";
+       case ARPHRD_CAN: return "can";
+       case ARPHRD_PPP: return "ppp";
+       case ARPHRD_HDLC: return "hdlc";
+       case ARPHRD_LAPB: return "lapb";
+       case ARPHRD_DDCMP: return "ddcmp";
+       case ARPHRD_RAWHDLC: return "rawhdlc";
+       case ARPHRD_TUNNEL: return "tunnel";
+       case ARPHRD_TUNNEL6: return "tunnel6";
+       case ARPHRD_FRAD: return "frad";
+       case ARPHRD_SKIP: return "skip";
+       case ARPHRD_LOOPBACK: return "loopback";
+       case ARPHRD_LOCALTLK: return "localtlk";
+       case ARPHRD_FDDI: return "fddi";
+       case ARPHRD_BIF: return "bif";
+       case ARPHRD_SIT: return "sit";
+       case ARPHRD_IPDDP: return "ipddp";
+       case ARPHRD_IPGRE: return "ipgre";
+       case ARPHRD_PIMREG: return "pimreg";
+       case ARPHRD_HIPPI: return "hippi";
+       case ARPHRD_ASH: return "ash";
+       case ARPHRD_ECONET: return "econet";
+       case ARPHRD_IRDA: return "irda";
+       case ARPHRD_FCPP: return "fcpp";
+       case ARPHRD_FCAL: return "fcal";
+       case ARPHRD_FCPL: return "fcpl";
+       case ARPHRD_FCFABRIC: return "fcfb0";
+       case ARPHRD_FCFABRIC + 1: return "fcfb1";
+       case ARPHRD_FCFABRIC + 2: return "fcfb2";
+       case ARPHRD_FCFABRIC + 3: return "fcfb3";
+       case ARPHRD_FCFABRIC + 4: return "fcfb4";
+       case ARPHRD_FCFABRIC + 5: return "fcfb5";
+       case ARPHRD_FCFABRIC + 6: return "fcfb6";
+       case ARPHRD_FCFABRIC + 7: return "fcfb7";
+       case ARPHRD_FCFABRIC + 8: return "fcfb8";
+       case ARPHRD_FCFABRIC + 9: return "fcfb9";
+       case ARPHRD_FCFABRIC + 10: return "fcfb10";
+       case ARPHRD_FCFABRIC + 11: return "fcfb11";
+       case ARPHRD_FCFABRIC + 12: return "fcfb12";
+       case ARPHRD_IEEE802_TR: return "ieee802_tr";
+       case ARPHRD_IEEE80211: return "ieee80211";
+       case ARPHRD_IEEE80211_PRISM: return "ieee80211_prism";
+       case ARPHRD_IEEE80211_RADIOTAP: return "ieee80211_radiotap";
+       case ARPHRD_IEEE802154: return "ieee802154";
+       case ARPHRD_PHONET: return "phonet";
+       case ARPHRD_PHONET_PIPE: return "phonet_pipe";
+       case ARPHRD_CAIF: return "caif";
+       case ARPHRD_IP6GRE: return "ip6gre";
+       case ARPHRD_NETLINK: return "netlink";
+       case ARPHRD_NONE: return "none";
+       case ARPHRD_VOID: return "void";
+
+       default: return "Unknown";
+       }
+}
+
+static const char *if_addr2str(const unsigned char *addr, int alen, int type,
+               char *buf, int blen)
+{
+       int i;
+       int l;
+
+       if (alen == 4 &&
+           (type == ARPHRD_TUNNEL || type == ARPHRD_SIT || type == 
ARPHRD_IPGRE)) {
+               return inet_ntop(AF_INET, addr, buf, blen);
+       }
+       if (alen == 16 && type == ARPHRD_TUNNEL6) {
+               return inet_ntop(AF_INET6, addr, buf, blen);
+       }
+       l = 0;
+       for (i=0; i<alen; i++) {
+               if (i==0) {
+                       snprintf(buf+l, blen, "%02x", addr[i]);
+                       blen -= 2;
+                       l += 2;
+               } else {
+                       snprintf(buf+l, blen, ":%02x", addr[i]);
+                       blen -= 3;
+                       l += 3;
+               }
+       }
+       return buf;
+}
+
 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
 {
        if (proto == NETLINK_ROUTE && type < RTM_MAX) {
@@ -133,6 +244,124 @@ static char *nlmsg_type2str(uint16_t proto, uint16_t 
type, char *buf, int len)
        return nl_nlmsgtype2str(type, buf, len);
 }
 
+static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
+{
+       struct ifinfomsg *ifi = NLMSG_DATA(hdr);
+       struct rtattr *attr = IFLA_RTA(ifi);
+       uint32_t attrs_len = IFLA_PAYLOAD(hdr);
+       char flags[256];
+       char if_addr[64] = {};
+       char *af_link = "Unknown";
+
+       if (ifi->ifi_family == 0)
+               af_link = "unspec";
+       else if (ifi->ifi_family == AF_BRIDGE)
+               af_link = "bridge";
+
+       tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
+                       colorize_start(bold), af_link, colorize_end());
+       tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
+                       colorize_start(bold),
+                       if_type2str(ifi->ifi_type),
+                       colorize_end());
+       tprintf(", Index %d", ifi->ifi_index);
+       tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
+                       colorize_start(bold),
+                       rtnl_link_flags2str(ifi->ifi_flags, flags,
+                               sizeof(flags)),
+                       colorize_end());
+       tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
+                       colorize_start(bold),
+                       rtnl_link_flags2str(ifi->ifi_change, flags,
+                               sizeof(flags)),
+                       colorize_end());
+
+       for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
+               switch (attr->rta_type) {
+               case IFLA_ADDRESS:
+                       tprintf("\tA: Address %s\n",
+                                       if_addr2str(RTA_DATA(attr),
+                                               RTA_PAYLOAD(attr),
+                                               ifi->ifi_type, if_addr,
+                                               sizeof(if_addr)));
+                       break;
+               case IFLA_BROADCAST:
+                       tprintf("\tA: Broadcast %s\n",
+                                       if_addr2str(RTA_DATA(attr),
+                                               RTA_PAYLOAD(attr),
+                                               ifi->ifi_type, if_addr,
+                                               sizeof(if_addr)));
+                       break;
+               case IFLA_IFNAME:
+                       tprintf("\tA: Name %s%s%s\n",
+                                       colorize_start(bold),
+                                       (char *)(RTA_DATA(attr)),
+                                       colorize_end());
+                       break;
+               case IFLA_MTU:
+                       tprintf("\tA: MTU %d\n", *(int *)(RTA_DATA(attr)));
+                       break;
+               case IFLA_LINK:
+                       tprintf("\tA: Link %d\n", *(int *)(RTA_DATA(attr)));
+                       break;
+               case IFLA_QDISC:
+                       tprintf("\tA: QDisc %s\n", (char *)(RTA_DATA(attr)));
+                       break;
+               case IFLA_OPERSTATE:
+                       {
+                               uint8_t st = *(uint8_t *)(RTA_DATA(attr));
+                               char states[256];
+
+                               tprintf("\tA: Operation state 0x%x (%s%s%s)\n",
+                                               st,
+                                               colorize_start(bold),
+                                               rtnl_link_operstate2str(st,
+                                                       states, sizeof(states)),
+                                               colorize_end());
+                       }
+                       break;
+               case IFLA_LINKMODE:
+                       {
+                               uint8_t mode = *(uint8_t *)(RTA_DATA(attr));
+                               char str[32];
+
+                               tprintf("\tA: Mode 0x%x (%s%s%s)\n", mode,
+                                               colorize_start(bold),
+                                               rtnl_link_mode2str(mode, str,
+                                                       sizeof(str)),
+                                               colorize_end());
+                       }
+                       break;
+               case IFLA_GROUP:
+                       tprintf("\tA: Group %d\n", *(int *)(RTA_DATA(attr)));
+                       break;
+               case IFLA_TXQLEN:
+                       tprintf("\tA: Tx queue len %d\n",
+                                       *(int *)(RTA_DATA(attr)));
+                       break;
+               case IFLA_NET_NS_PID:
+                       tprintf("\tA: Network namespace pid %d\n",
+                                       *(int *)(RTA_DATA(attr)));
+                       break;
+               case IFLA_NET_NS_FD:
+                       tprintf("\tA: Network namespace fd %d\n",
+                                       *(int *)(RTA_DATA(attr)));
+                       break;
+               }
+       }
+}
+
+static void rtnl_msg_print(struct nlmsghdr *hdr)
+{
+       switch (hdr->nlmsg_type) {
+       case RTM_NEWLINK:
+       case RTM_DELLINK:
+       case RTM_GETLINK:
+       case RTM_SETLINK:
+               rtnl_print_ifinfo(hdr);
+       }
+}
+
 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
 {
        char type[32];
@@ -178,6 +407,9 @@ static void nlmsg_print(uint16_t family, struct nlmsghdr 
*hdr)
                tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
                        colorize_end());
        tprintf(" ]\n");
+
+       if (family == NETLINK_ROUTE)
+               rtnl_msg_print(hdr);
 }
 
 static void nlmsg(struct pkt_buff *pkt)
-- 
2.3.1

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to