Created
March 28, 2016 20:56
-
-
Save j-marjanovic/47110bca4f37a13bf197 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/netlink.h> | |
#include <linux/rtnetlink.h> | |
#include <net/if.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
// from https://gist.github.com/ccbrown/9722406 | |
void DumpHex(const void* data, size_t size) { | |
char ascii[17]; | |
size_t i, j; | |
ascii[16] = '\0'; | |
for (i = 0; i < size; ++i) { | |
printf("%02X ", ((unsigned char*)data)[i]); | |
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { | |
ascii[i % 16] = ((unsigned char*)data)[i]; | |
} else { | |
ascii[i % 16] = '.'; | |
} | |
if ((i+1) % 8 == 0 || i+1 == size) { | |
printf(" "); | |
if ((i+1) % 16 == 0) { | |
printf("| %s \n", ascii); | |
} else if (i+1 == size) { | |
ascii[(i+1) % 16] = '\0'; | |
if ((i+1) % 16 <= 8) { | |
printf(" "); | |
} | |
for (j = (i+1) % 16; j < 16; ++j) { | |
printf(" "); | |
} | |
printf("| %s \n", ascii); | |
} | |
} | |
} | |
} | |
void print_netlink_header(struct nlmsghdr *hdr) { | |
printf("Netlink header:\n"); | |
printf(" nlmsg_len: %d\n", hdr->nlmsg_len); | |
printf(" nlmsg_type: %d\n", hdr->nlmsg_type); | |
printf(" nlmsg_flags: %d\n", hdr->nlmsg_flags); | |
printf(" nlmsg_seq: %d\n", hdr->nlmsg_seq); | |
printf(" nlmsg_pid: %d\n", hdr->nlmsg_pid); | |
} | |
//http://lxr.free-electrons.com/source/include/uapi/linux/if.h#L70 | |
void print_if_flags(int if_flags){ | |
int i; | |
int found; | |
const char *name; | |
for(i=0; i < 32; i++){ | |
found = 1; | |
switch(if_flags & (1<<i)) { | |
case IFF_UP: name = "IFF_UP"; break; | |
case IFF_BROADCAST: name = "IFF_BROADCAST"; break; | |
case IFF_DEBUG: name = "IFF_DEBUG"; break; | |
case IFF_LOOPBACK: name = "IFF_LOOPBACK"; break; | |
case IFF_POINTOPOINT: name = "IFF_POINTOPOINT"; break; | |
case IFF_NOTRAILERS: name = "IFF_NOTRAILERS"; break; | |
case IFF_RUNNING: name = "IFF_RUNNING"; break; | |
case IFF_NOARP: name = "IFF_NOARP"; break; | |
case IFF_PROMISC: name = "IFF_PROMISC"; break; | |
case IFF_ALLMULTI: name = "IFF_ALLMULTI"; break; | |
case IFF_MASTER: name = "IFF_MASTER"; break; | |
case IFF_SLAVE: name = "IFF_SLAVE"; break; | |
case IFF_MULTICAST: name = "IFF_MULTICAST"; break; | |
case IFF_PORTSEL: name = "IFF_PORTSEL"; break; | |
case IFF_AUTOMEDIA: name = "IFF_AUTOMEDIA"; break; | |
case IFF_DYNAMIC: name = "IFF_DYNAMIC"; break; | |
//case IFF_LOWER_UP: name = "IFF_LOWER_UP"; break; | |
//case IFF_DORMANT: name = "IFF_DORMANT"; break; | |
//case IFF_ECHO: name = "IFF_ECHO"; break; | |
default: found = 0; //printf("not found: %d\n", i); | |
} | |
if (found) { | |
printf("%s%s", (i != 0) ? ", " : "", name); | |
} | |
} | |
} | |
void print_if_info_msg(struct ifinfomsg *msg) { | |
printf("Interface info message:\n"); | |
printf(" ifi_family: %d\n", msg->ifi_family); | |
printf(" ifi_type: %d\n", msg->ifi_type); | |
printf(" ifi_index: %d\n", msg->ifi_index); | |
printf(" ifi_flags: 0x%x\n", msg->ifi_flags); | |
printf(" flags: "); print_if_flags(msg->ifi_flags); printf("\n"); | |
printf(" ifi_change: %d\n", msg->ifi_change); | |
} | |
void print_rta_type(int type) { | |
switch (type) { | |
case IFLA_UNSPEC: printf("IFLA_UNSPEC (%d)", IFLA_UNSPEC); break; | |
case IFLA_ADDRESS: printf("IFLA_ADDRESS (%d)", IFLA_ADDRESS); break; | |
case IFLA_BROADCAST: printf("IFLA_BROADCAST (%d)", IFLA_BROADCAST); break; | |
case IFLA_IFNAME: printf("IFLA_IFNAME (%d)", IFLA_IFNAME); break; | |
case IFLA_MTU: printf("IFLA_MTU (%d)", IFLA_MTU); break; | |
case IFLA_LINK: printf("IFLA_LINK (%d)", IFLA_LINK); break; | |
case IFLA_QDISC: printf("IFLA_QDISC (%d)", IFLA_QDISC); break; | |
case IFLA_STATS: printf("IFLA_STATS (%d)", IFLA_STATS); break; | |
case IFLA_COST: printf("IFLA_COST (%d)", IFLA_COST); break; | |
case IFLA_PRIORITY: printf("IFLA_PRIORITY (%d)", IFLA_PRIORITY); break; | |
case IFLA_MASTER: printf("IFLA_MASTER (%d)", IFLA_MASTER); break; | |
case IFLA_WIRELESS: printf("IFLA_WIRELESS (%d)", IFLA_WIRELESS); break; | |
case IFLA_PROTINFO: printf("IFLA_PROTINFO (%d)", IFLA_PROTINFO); break; | |
case IFLA_TXQLEN: printf("IFLA_TXQLEN (%d)", IFLA_TXQLEN); break; | |
case IFLA_MAP: printf("IFLA_MAP (%d)", IFLA_MAP); break; | |
case IFLA_WEIGHT: printf("IFLA_WEIGHT (%d)", IFLA_WEIGHT); break; | |
case IFLA_OPERSTATE: printf("IFLA_OPERSTATE (%d)", IFLA_OPERSTATE); break; | |
case IFLA_LINKMODE: printf("IFLA_LINKMODE (%d)", IFLA_LINKMODE); break; | |
case IFLA_LINKINFO: printf("IFLA_LINKINFO (%d)", IFLA_LINKINFO); break; | |
case IFLA_NET_NS_PID: printf("IFLA_NET_NS_PID (%d)", IFLA_NET_NS_PID); break; | |
case IFLA_IFALIAS: printf("IFLA_IFALIAS (%d)", IFLA_IFALIAS); break; | |
case IFLA_NUM_VF: printf("IFLA_NUM_VF (%d)", IFLA_NUM_VF); break; | |
case IFLA_VFINFO_LIST: printf("IFLA_VFINFO_LIST (%d)", IFLA_VFINFO_LIST); break; | |
case IFLA_STATS64: printf("IFLA_STATS64 (%d)", IFLA_STATS64); break; | |
case IFLA_VF_PORTS: printf("IFLA_VF_PORTS (%d)", IFLA_VF_PORTS); break; | |
case IFLA_PORT_SELF: printf("IFLA_PORT_SELF (%d)", IFLA_PORT_SELF); break; | |
case IFLA_AF_SPEC: printf("IFLA_AF_SPEC (%d)", IFLA_AF_SPEC); break; | |
case IFLA_GROUP: printf("IFLA_GROUP (%d)", IFLA_GROUP); break; | |
case IFLA_NET_NS_FD: printf("IFLA_NET_NS_FD (%d)", IFLA_NET_NS_FD); break; | |
case IFLA_EXT_MASK: printf("IFLA_EXT_MASK (%d)", IFLA_EXT_MASK); break; | |
case IFLA_PROMISCUITY: printf("IFLA_PROMISCUITY (%d)", IFLA_PROMISCUITY); break; | |
case IFLA_NUM_TX_QUEUES: printf("IFLA_NUM_TX_QUEUES (%d)", IFLA_NUM_TX_QUEUES); break; | |
case IFLA_NUM_RX_QUEUES: printf("IFLA_NUM_RX_QUEUES (%d)", IFLA_NUM_RX_QUEUES); break; | |
case IFLA_CARRIER: printf("IFLA_CARRIER (%d)", IFLA_CARRIER); break; | |
case IFLA_PHYS_PORT_ID: printf("IFLA_PHYS_PORT_ID (%d)", IFLA_PHYS_PORT_ID); break; | |
case IFLA_CARRIER_CHANGES: printf("IFLA_CARRIER_CHANGES (%d)", IFLA_CARRIER_CHANGES); break; | |
} | |
} | |
int main() { | |
int rc; | |
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | |
if (sock < 0) { | |
perror("socket()"); | |
exit(EXIT_FAILURE); | |
} | |
printf("socket(): %d\n", sock); | |
struct sockaddr_nl recv_addr; | |
memset(&recv_addr, 0, sizeof(recv_addr)); | |
recv_addr.nl_family = AF_NETLINK; | |
recv_addr.nl_pid = getpid(); | |
recv_addr.nl_groups = 0; | |
rc = bind(sock, (struct sockaddr*)&recv_addr, sizeof(recv_addr)); | |
if (rc < 0) { | |
perror("bind()"); | |
exit(EXIT_FAILURE); | |
} | |
printf("bind(): %d\n", rc); | |
struct sockaddr_nl dest_addr; | |
memset(&dest_addr, 0, sizeof(dest_addr)); | |
dest_addr.nl_family = AF_NETLINK; | |
dest_addr.nl_pid = 0; | |
dest_addr.nl_groups = 0; | |
struct { | |
struct nlmsghdr nh; | |
struct ifinfomsg ifmsg; | |
char attrbuf[512]; | |
} req; | |
struct rtattr *rta; | |
memset(&req, 0, sizeof(req)); | |
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); | |
req.nh.nlmsg_flags = NLM_F_REQUEST; | |
req.nh.nlmsg_type = RTM_GETLINK; | |
req.ifmsg.ifi_family = AF_UNSPEC; | |
req.ifmsg.ifi_index = 3; // TODO: get interface index | |
req.ifmsg.ifi_change = 0xffffffff; /* ??? */ | |
rta = (struct rtattr *)(((char *) &req) + | |
NLMSG_ALIGN(req.nh.nlmsg_len)); | |
rta->rta_type = IFLA_STATS; | |
rta->rta_len = RTA_LENGTH(sizeof(unsigned int)); | |
req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + | |
RTA_LENGTH(sizeof(struct rtnl_link_stats)); | |
rc = send(sock, &req, req.nh.nlmsg_len, 0); | |
if (rc < 0) { | |
perror("send()"); | |
exit(EXIT_FAILURE); | |
} | |
printf("send(): %d\n", rc); | |
char buf[4096]; | |
rc = recv(sock, &buf, 4096, 0); | |
if (rc < 0) { | |
perror("recv()"); | |
exit(EXIT_FAILURE); | |
} | |
printf("recv(): %d\n", rc); | |
printf("=====================================================================\n"); | |
DumpHex(buf, rc); | |
printf("=====================================================================\n"); | |
struct nlmsghdr *recv_hdr = (struct nlmsghdr*)buf; | |
print_netlink_header(recv_hdr); | |
struct ifinfomsg *infomsg = NLMSG_DATA(recv_hdr); | |
print_if_info_msg(infomsg); | |
rta = IFLA_RTA(infomsg); | |
int len = recv_hdr->nlmsg_len; | |
printf("Routing attributes:\n"); | |
while (RTA_OK(rta, len)){ | |
printf(" "); print_rta_type(rta->rta_type); printf("\n"); | |
if (rta->rta_type == IFLA_STATS) { | |
struct rtnl_link_stats *stats = RTA_DATA(rta); | |
printf(" RX bytes: %u MB\n", stats->rx_bytes/1024/1024); | |
printf(" TX bytes: %u MB\n", stats->tx_bytes/1024/1024); | |
} else if (rta->rta_type == IFLA_STATS64) { | |
struct rtnl_link_stats64 *stats64 = RTA_DATA(rta); | |
printf(" RX bytes: %llu MB\n", stats64->rx_bytes/1024/1024); | |
printf(" TX bytes: %llu MB\n", stats64->tx_bytes/1024/1024); | |
} | |
rta = RTA_NEXT(rta, len); | |
} | |
close(sock); | |
exit(EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment