diff options
author | Vadim Kochan <vadim4j@gmail.com> | 2015-05-19 17:10:38 +0300 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2015-06-01 01:18:25 +0200 |
commit | 107456c646ab38e5ccb6ee788389faced59c16ff (patch) | |
tree | 4db201d48c9078e72ad89d126fe396f1fe685306 | |
parent | d0677020ce89fc087925467480d75428df52dc95 (diff) |
netsniff-ng, nlmsg: Dissect rtnl link type messages
Dump RTnetlink interface related info with attributes.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r-- | netsniff-ng/Makefile | 2 | ||||
-rw-r--r-- | proto_nlmsg.c | 233 |
2 files changed, 235 insertions, 0 deletions
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..89b48b2 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,115 @@ 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"; + } +} + +/* Taken from iproute2 */ +static const char *ll_addr_n2a(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 +245,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 == AF_UNSPEC) + 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", + ll_addr_n2a(RTA_DATA(attr), + RTA_PAYLOAD(attr), + ifi->ifi_type, if_addr, + sizeof(if_addr))); + break; + case IFLA_BROADCAST: + tprintf("\tA: Broadcast %s\n", + ll_addr_n2a(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 +408,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) |