From 2125e835a1beab06413c4c3b254e8a529208280a Mon Sep 17 00:00:00 2001 From: Anjali Kulkarni Date: Mon, 5 Feb 2024 16:54:35 -0800 Subject: [PATCH] Re-arrange net_* files efficiently Moved common functionality between net_*.c files into net.c. Moved the handle_*_resp() calls for route, arp & if into handle_net_resp() Added new tests/IF directory for interface statistics. Removed the path outside while loop as it will never be run. Added err1 and err2 paths for error handling in net.c Fixed issues in net_if.c - missing bzero for ifs, and writing the interface name when TESTING is not enabled. Also added some extra prints and a free in tests/IF/if_test.c Signed-off-by: Anjali Kulkarni --- Makefile | 4 +- net.c | 374 +++++++++++++++++++++++++++++++++++++++ net.h | 30 ++++ net_arp.c | 229 +----------------------- net_if.c | 236 +++--------------------- net_route.c | 234 ++---------------------- resource.c | 2 +- resource.h | 4 +- tests/ARP/arp_test.c | 3 +- tests/IF/if.sh | 8 + tests/IF/if_test.c | 29 +++ tests/ROUTE/route_test.c | 3 +- tests/STAT/stat_test.c | 6 +- 13 files changed, 502 insertions(+), 660 deletions(-) create mode 100644 net.c create mode 100644 net.h create mode 100755 tests/IF/if.sh create mode 100644 tests/IF/if_test.c diff --git a/Makefile b/Makefile index 846c496..0b515bd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -g -Wall -Werror -fPIC -std=gnu99 -DEPS = resource.h resource_impl.h resmem.h resnet.h resproc.h resvm.h rescpu.h resfs.h stat.h -OBJ = resource.o resmem.o resnet.o resproc.o reskern.o resvm.o rescpu.o resfs.o net_if.o net_route.o net_arp.o stat.o resmem_cg.o +DEPS = resource.h resource_impl.h resmem.h resnet.h resproc.h resvm.h rescpu.h resfs.h stat.h net.h +OBJ = resource.o resmem.o resnet.o resproc.o reskern.o resvm.o rescpu.o resfs.o net_if.o net_route.o net_arp.o stat.o resmem_cg.o net.o TEST = test RM = rm -rf CP = cp diff --git a/net.c b/net.c new file mode 100644 index 0000000..34a2234 --- /dev/null +++ b/net.c @@ -0,0 +1,374 @@ +#ifndef _RESOURCE_H +#include "resource.h" +#endif +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "resource_impl.h" +#include "net.h" + +static int count, ecount; + +int connect_netlink(int groups) +{ + struct sockaddr_nl nl_saddr; + int err, net_sock; + + net_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (net_sock == -1) { + err = errno; + eprintf("Error in socket(), errno %d\n", err); + return -err; + } + bzero(&nl_saddr, sizeof(nl_saddr)); + nl_saddr.nl_family = AF_NETLINK; + if (groups) + nl_saddr.nl_groups = RTMGRP_NEIGH; + + err = bind(net_sock, (struct sockaddr *)&nl_saddr, sizeof(nl_saddr)); + if (err == -1) { + err = errno; + eprintf("Error in bind(), errno %d\n", err); + close(net_sock); + return -err; + } + return net_sock; +} + +int get_net_len(int net_sock) +{ + int recvl, err; + struct msghdr msg; + struct iovec iov; + struct sockaddr_nl nladdr; + + memset(&msg, 0, sizeof(msg)); + memset(&iov, 0, sizeof(iov)); + + msg.msg_name = &nladdr; + msg.msg_namelen = sizeof(nladdr); + iov.iov_base = NULL; + iov.iov_len = 0; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + recvl = recvmsg(net_sock, &msg, MSG_PEEK | MSG_TRUNC); + if (recvl < 0) { + err = errno; + eprintf("Error in get length recvmsg(), errno %d\n", err); + return -err; + } +#ifdef PRINTLOGS + printf("received len %d\n",recvl); +#endif + return recvl; +} + +static inline int get_max_net(int net_type, int len) +{ + int header_size, net_sz; + + switch(net_type) { + case NET_ROUTE: + net_sz = sizeof(struct rtmsg); + break; + case NET_ARP: + net_sz = sizeof(struct ndmsg); + break; + case NET_IF: + net_sz = (sizeof(struct if_stats_msg)) + + (sizeof(struct rtnl_link_stats64)); + break; + } + header_size = (sizeof(struct nlmsghdr)) + net_sz; + return (len/header_size); +} + +static inline int sz_net(int net_type) +{ + switch(net_type) { + case NET_ROUTE: + return (sizeof(struct rt_info)); + case NET_ARP: + return (sizeof(struct arp_info)); + case NET_IF: + return (sizeof(struct ifstats)); + } + return 0; +} + +char net_file[3][20] = {"./route_info.txt", + "./arp_info.txt", + "./if_info.txt"}; + +static inline bool check_family_type(unsigned int family, unsigned int type) +{ + if (family == AF_INET || family == AF_INET6) { + if ((type == RTN_BROADCAST) || + (type == RTN_MULTICAST) || + (type == RTN_LOCAL)) { + return true; + } + return false; + } else { + return true; + } +} + +int handle_net_resp(int net_type, int net_sock, void **out) +{ + int recvl, len, max_net, net_size; + int netind = 0, total_net_size = 0, ret = 0; + struct iovec iov; + struct msghdr msg; + struct nlmsghdr *r; + struct nlmsgerr *nlmsg_err; + struct sockaddr_nl nladdr; + char *buf; + void *ntwrks = NULL; + struct rtmsg *rt; + struct rtattr *at[RTA_MAX + 1]; + struct rt_info *iroutes = NULL; + struct ndmsg *nd_msg; + struct rtattr *at_arp[NDA_MAX + 1], *rta; + struct arp_info *iarps = NULL; + struct if_stats_msg *ifsm; + struct rtattr *at_if[IFLA_STATS_MAX+1], *rta_if; + struct ifstats *ifs = NULL; + +#ifdef TESTING + FILE *fp; + fp = fopen(net_file[net_type], "w"); + if (!fp) { + eprintf("Error opening file %s with errno: %d", + net_file[net_type], errno); + return -1; + } +#endif + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &nladdr; + msg.msg_namelen = sizeof(nladdr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + while(1) { + len = get_net_len(net_sock); + if (len < 0) { + ret = len; + goto err1; + } + buf = (char *)malloc(len); + if (!buf) { + ret = -ENOMEM; + goto err1; + } + memset(&iov, 0, sizeof(iov)); + iov.iov_base = buf; + iov.iov_len = len; + max_net = get_max_net(net_type, len); + net_size = max_net * sz_net(net_type); + total_net_size += net_size; + + void *tmp = realloc(ntwrks, total_net_size); + if (!tmp) { + ret = -ENOMEM; + goto err2; + } + ntwrks = tmp; + + switch(net_type) { + case NET_ROUTE: + iroutes = (struct rt_info *)ntwrks + netind; + break; + case NET_ARP: + iarps = (struct arp_info *)ntwrks + netind; + break; + case NET_IF: + ifs = (struct ifstats *)ntwrks + netind; + break; + } + + recvl = recvmsg(net_sock, &msg, 0); + if (recvl < 0) { + ret = -errno; + eprintf("Error in resp recvmsg(), errno %d\n", -ret); + goto err2; + } + r = (struct nlmsghdr *) buf; +#ifdef PRINTLOGS + printf("recvmsg len %d\n", recvl); + printf("r->nlmsg_type is %d\n", r->nlmsg_type); +#endif + while (NLMSG_OK(r, recvl)) { + if (r->nlmsg_type == NLMSG_ERROR) { + nlmsg_err = (struct nlmsgerr *)NLMSG_DATA(r); + eprintf("NLMSG_ERROR error: %d\n", + nlmsg_err->error); + ecount++; + ret = -(nlmsg_err->error); + goto err2; + } else if (r->nlmsg_type == NLMSG_DONE) { +#ifdef PRINTLOGS + printf("DONE\n"); +#endif + free(buf); + switch(net_type) { + case NET_ROUTE: + *(struct rt_info **)out = + (struct rt_info *)ntwrks; + break; + case NET_ARP: + *(struct arp_info **)out = + (struct arp_info *)ntwrks; + break; + case NET_IF: + *(struct ifstats **)out = + (struct ifstats *)ntwrks; + break; + } + ret = netind; + goto out; + } + len = r->nlmsg_len; + switch (net_type) { + case NET_ROUTE: + if (r->nlmsg_type != RTM_NEWROUTE) { + printf("r->nlmsg_type incorrect %u\n", + r->nlmsg_type); + ret = -EINVAL; + goto err2; + } + rt = (struct rtmsg *)NLMSG_DATA(r); + len -= NLMSG_LENGTH(sizeof(*rt)); + if (len < 0) { + eprintf("nlmsg_len incorrect"); + ret = -EINVAL; + goto err2; + } +#ifdef PRINTLOGS + print_rt(rt); + printf("len after sub %lu is %d\n", + sizeof(*rt), len); +#endif + parse_rt_attr(at, RTM_RTA(rt), len); + if (check_family_type(rt->rtm_family, + rt->rtm_type)) { + r = NLMSG_NEXT(r, recvl); + continue; + } + get_rt_attr(at, iroutes, rt); +#ifdef TESTING + print_rt_info(iroutes, fp); +#endif + iroutes++; + netind++; + break; + case NET_ARP: + if (r->nlmsg_type != RTM_NEWNEIGH) { + printf("r->nlmsg_type incorrect %u\n", + r->nlmsg_type); + ret = -EINVAL; + goto err2; + } + nd_msg = (struct ndmsg *)NLMSG_DATA(r); + len -= NLMSG_LENGTH(sizeof(*nd_msg)); + if (len < 0) { + eprintf("nlmsg_len incorrect"); + ret = -EINVAL; + goto err2; + } +#ifdef PRINTLOGS + print_arp(nd_msg); + printf("len after sub %lu is %d\n", + sizeof(*nd_msg), len); +#endif + rta = ((struct rtattr *) (((char *) (nd_msg)) + NLMSG_ALIGN(sizeof(struct ndmsg)))); + parse_arp_attr(at_arp, rta, len); + if (check_family_type(nd_msg->ndm_family, + nd_msg->ndm_type)) { + r = NLMSG_NEXT(r, recvl); + continue; + } +#ifdef TESTING + get_arp_attr(at_arp, iarps, nd_msg, fp); +#else + get_arp_attr(at_arp, iarps, nd_msg); +#endif + iarps++; + netind++; + break; + case NET_IF: + if (r->nlmsg_type != RTM_NEWSTATS) { + printf("r->nlmsg_type incorrect %u\n", + r->nlmsg_type); + ret = -EINVAL; + goto err2; + } + ifsm = (struct if_stats_msg *)NLMSG_DATA(r); + len -= NLMSG_LENGTH(sizeof(*ifsm)); + if (len < 0) { + eprintf("nlmsg_len incorrect"); + ret = -EINVAL; + goto err2; + } +#ifdef PRINTLOGS + printf("ifindex is %d\n", ifsm->ifindex); + printf("len after sub %lu is %d\n", + sizeof(*ifsm), len); +#endif + rta_if = ((struct rtattr *)(((char *)(ifsm)) + NLMSG_ALIGN(sizeof(struct if_stats_msg)))); + parse_if_attr(at_if, rta_if, len); + bzero(ifs, sizeof(*ifs)); + if (if_indextoname(ifsm->ifindex, + ifs->ifname) == NULL) { + printf("Error in if_indextoname %d\n", + errno); + ret = -EINVAL; + goto err2; + } + memcpy(&ifs->st64, + RTA_DATA(at_if[IFLA_STATS_LINK_64]), + sizeof(*ifs)); +#ifdef TESTING + //print_if_info(ifs, fp); +#endif +#ifdef PRINTLOGS + print_if(ifs); +#endif + ifs++; + netind++; + break; + } + r = NLMSG_NEXT(r, recvl); + count++; + } + free(buf); +#ifdef PRINTLOGS + printf("No. of routes/arp/if: %d\n",netind); +#endif + } +err2: + free(buf); +err1: + if (ntwrks) + free(ntwrks); +out: +#ifdef TESTING + if (fp) + fclose(fp); +#endif + return ret; +} diff --git a/net.h b/net.h new file mode 100644 index 0000000..c096b00 --- /dev/null +++ b/net.h @@ -0,0 +1,30 @@ +enum { + NET_ROUTE, + NET_ARP, + NET_IF, + NET_MAX +}; + +//extern char net_file[3][20]; + +extern int connect_netlink(int groups); +extern int get_net_len(int net_sock); +extern int parse_rt_attr(struct rtattr *at[], struct rtattr *rta, int len); +extern void print_rt(struct rtmsg *rt); +extern int handle_net_resp(int net_type, int net_sock, void **out); +extern void print_rt_info(struct rt_info *rt, FILE *fp); +extern int get_rt_attr(struct rtattr *at[], struct rt_info *rt, struct rtmsg *m); +extern int parse_arp_attr(struct rtattr *at[], struct rtattr *rta, int len); +#ifdef TESTING +extern int get_arp_attr(struct rtattr *at[], struct arp_info *arp, + struct ndmsg *n, + FILE *fp); +#else +extern int get_arp_attr(struct rtattr *at[], struct arp_info *arp, + struct ndmsg *n); +#endif +extern int parse_if_attr(struct rtattr *at[], struct rtattr *rta, int len); +#ifdef TESTING +extern void print_if_info(struct ifstats *ifs, FILE *fp); +#endif +extern void print_if(struct ifstats *ifs); diff --git a/net_arp.c b/net_arp.c index 83d9208..4566ceb 100644 --- a/net_arp.c +++ b/net_arp.c @@ -15,33 +15,8 @@ #include #include #include "resource_impl.h" +#include "net.h" -static int count, ecount; - -static int connect_arp() -{ - struct sockaddr_nl nl_saddr; - int err, net_sock; - - net_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (net_sock == -1) { - err = errno; - eprintf("Error in socket(), errno %d\n", err); - return -err; - } - bzero(&nl_saddr, sizeof(nl_saddr)); - nl_saddr.nl_family = AF_NETLINK; - nl_saddr.nl_groups = RTMGRP_NEIGH; - err = bind(net_sock, (struct sockaddr *)&nl_saddr, sizeof(nl_saddr)); - if (err == -1) { - err = errno; - eprintf("Error in bind(), errno %d\n", err); - close(net_sock); - return -err; - } - return net_sock; -} - static int send_arp_req(int net_sock) { int err; @@ -68,7 +43,7 @@ static int send_arp_req(int net_sock) return 0; } -static int parse_attr(struct rtattr *at[], struct rtattr *rta, int len) +int parse_arp_attr(struct rtattr *at[], struct rtattr *rta, int len) { memset(at, 0, sizeof(struct rtattr *) * (NDA_MAX + 1)); while (RTA_OK(rta, len)) { @@ -79,49 +54,13 @@ static int parse_attr(struct rtattr *at[], struct rtattr *rta, int len) return 0; } -static int get_arp_len(int net_sock) -{ - int recvl, err; - struct msghdr msg; - struct iovec iov; - struct sockaddr_nl nladdr; - - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - msg.msg_name = &nladdr; - msg.msg_namelen = sizeof(nladdr); - iov.iov_base = NULL; - iov.iov_len = 0; - - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - recvl = recvmsg(net_sock, &msg, MSG_PEEK | MSG_TRUNC); - if (recvl < 0) { - err = errno; - eprintf("Error in get length recvmsg(), errno %d\n", err); - return -err; - } -#ifdef PRINTLOGS1 - printf("received len %d\n",recvl); -#endif - return recvl; -} - -static int get_max_arp(int len) -{ - int header_size, max_arp; - header_size = (sizeof(struct nlmsghdr)) + (sizeof(struct ndmsg)); - max_arp = len/header_size; - return max_arp; -} - #ifdef TESTING -static int get_attr(struct rtattr *at[], struct arp_info *arp, struct ndmsg *n, +int get_arp_attr(struct rtattr *at[], struct arp_info *arp, + struct ndmsg *n, FILE *fp) #else -static int get_attr(struct rtattr *at[], struct arp_info *arp, struct ndmsg *n) +int get_arp_attr(struct rtattr *at[], struct arp_info *arp, + struct ndmsg *n) #endif { #ifdef TESTING @@ -160,160 +99,11 @@ static int get_attr(struct rtattr *at[], struct arp_info *arp, struct ndmsg *n) return 0; } -static int handle_arp_resp(int net_sock, void **out) -{ - int recvl, len, max_arp, arp_size, ret = 0; - int aind = 0, total_arp_size = 0; - struct iovec iov; - struct msghdr msg; - struct nlmsghdr *r; - struct nlmsgerr *nlmsg_err; - struct ndmsg *nd_msg; - struct rtattr *at[NDA_MAX + 1], *rta; - struct arp_info *arps = NULL, *iarps = NULL; - struct sockaddr_nl nladdr; - unsigned int type, family; -#ifdef TESTING - FILE *fp; - fp = fopen("./arp_info.txt", "w"); - if (!fp) { - eprintf("Error opening file arp_info.txt with errno: %d", errno); - return -1; - } -#endif - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &nladdr; - msg.msg_namelen = sizeof(nladdr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - while(1) { - len = get_arp_len(net_sock); - if (len < 0) { - if (arps) - free(arps); - ret = len; - goto out; - } - char *buf = (char *)malloc(len); - if (!buf) { - if (arps) - free(arps); - ret = -ENOMEM; - goto out; - } - memset(&iov, 0, sizeof(iov)); - iov.iov_base = buf; - iov.iov_len = len; - max_arp = get_max_arp(len); - arp_size = max_arp * sizeof(struct arp_info); - total_arp_size += arp_size; - - void *tmp = (struct arp_info *) realloc(arps, total_arp_size); - if (!tmp) { - if (arps) - free(arps); - free(buf); - ret = -ENOMEM; - goto out; - } - arps = tmp; - iarps = arps + aind; - - recvl = recvmsg(net_sock, &msg, 0); - if (recvl < 0) { - ret = -errno; - free(arps); - free(buf); - eprintf("Error in response recvmsg(), errno %d\n", -ret); - goto out; - } -#ifdef PRINTLOGS - printf("received len %d\n",recvl); -#endif - r = (struct nlmsghdr *) buf; - while (NLMSG_OK(r, recvl)) { - if (r->nlmsg_type == NLMSG_ERROR) { - nlmsg_err = (struct nlmsgerr *)NLMSG_DATA(r); - eprintf("NLMSG_ERROR error: %d\n", - nlmsg_err->error); - ecount++; - free(buf); - free(arps); - ret = -(nlmsg_err->error); - goto out; - } else if (r->nlmsg_type == NLMSG_DONE) { -#ifdef PRINTLOGS - printf("DONE\n"); -#endif - free(buf); - *(struct arp_info **)out = arps; - ret = aind; - goto out; - } - nd_msg = (struct ndmsg *)NLMSG_DATA(r); - len = r->nlmsg_len; -#ifdef PRINTLOGS - printf("r->nlmsg_type is %d (RTM_NEWNEIGH = 28)\n", r->nlmsg_type); - printf("Received ndmsg, len %d\n", len); - printf("ifindex is %d\n", nd_msg->ndm_ifindex); - printf("family: %u\n", nd_msg->ndm_family); - printf("ndm_type: %u\n", nd_msg->ndm_type); - printf("ndm_flags: %u\n",nd_msg->ndm_flags); - printf("ndm_state: %u\n", nd_msg->ndm_state); -#endif - len -= NLMSG_LENGTH(sizeof(*nd_msg)); - if (len < 0) { - eprintf("nlmsg_len incorrect"); - free(buf); - free(arps); - ret = -EINVAL; - goto out; - } -#ifdef PRINTLOGS - printf("len after sub %ld is %d\n",sizeof(*nd_msg), len); -#endif - rta = ((struct rtattr *) (((char *) (nd_msg)) + NLMSG_ALIGN(sizeof(struct ndmsg)))); - parse_attr(at, rta, len); - family = nd_msg->ndm_family; - type = nd_msg->ndm_type; - if (family == AF_INET || family == AF_INET6) { - if ((type == RTN_BROADCAST) || - (type == RTN_MULTICAST) || - (type == RTN_LOCAL)) { - r = NLMSG_NEXT(r, recvl); - continue; - } -#ifdef TESTING - get_attr(at, iarps, nd_msg, fp); -#else - get_attr(at, iarps, nd_msg); -#endif - iarps++; - aind++; - } - r = NLMSG_NEXT(r, recvl); - count++; - } - free(buf); - printf("No. of ARPs: %d\n",aind); - } - *(struct arp_info **)out = arps; - ret = aind; -out: -#ifdef TESTING - if (fp) - fclose(fp); -#endif - return ret; -} - int get_net_arp(void **out) { int err, net_sock; - net_sock = connect_arp(); + net_sock = connect_netlink(1); if (net_sock < 0) return net_sock; @@ -323,7 +113,7 @@ int get_net_arp(void **out) return err; } - err = handle_arp_resp(net_sock, out); + err = handle_net_resp(NET_ARP, net_sock, out); close(net_sock); return err; } @@ -339,8 +129,7 @@ int getarpinfo(int res_id, void *out, size_t sz, void **hint, int flags) break; default: eprintf("Resource Id is invalid"); - errno = EINVAL; - return -1; + return -EINVAL; } return len; } diff --git a/net_if.c b/net_if.c index 0e80243..2c0968c 100644 --- a/net_if.c +++ b/net_if.c @@ -15,37 +15,7 @@ #include #include #include "resource_impl.h" - -//#define PRINTLOGS - -static int ecount, count; - -static int connect_dev() -{ - struct sockaddr_nl nl_saddr; - int err, net_sock; - - net_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (net_sock == -1) { - err = errno; - eprintf("Error in socket(), errno %d\n", err); - errno = err; - return -1; - } - bzero(&nl_saddr, sizeof(nl_saddr)); - nl_saddr.nl_family = AF_NETLINK; - //nl_saddr.nl_pid = getpid(); - - err = bind(net_sock, (struct sockaddr *)&nl_saddr, sizeof(nl_saddr)); - if (err == -1) { - err = errno; - eprintf("Error in bind(), errno %d\n", err); - close(net_sock); - errno = err; - return -1; - } - return net_sock; -} +#include "net.h" static int send_stats_req(int net_sock) { @@ -70,13 +40,12 @@ static int send_stats_req(int net_sock) if (err == -1) { err = errno; eprintf("Error in request send(), errno %d\n", err); - errno = err; - return -1; + return -err; } return 0; } -static int parse_attr(struct rtattr *at[], struct rtattr *rta, int len) +int parse_if_attr(struct rtattr *at[], struct rtattr *rta, int len) { memset(at, 0, sizeof(struct rtattr *) * (IFLA_STATS_MAX + 1)); while (RTA_OK(rta, len)) { @@ -87,194 +56,40 @@ static int parse_attr(struct rtattr *at[], struct rtattr *rta, int len) return 0; } -static int get_if_len(int net_sock) +void print_if_info(struct ifstats *ifs, FILE *fp) { - int recvl, err; - struct msghdr msg; - struct iovec iov; - struct sockaddr_nl nladdr; - - msg.msg_name = &nladdr; - msg.msg_namelen = sizeof(nladdr); - iov.iov_base = NULL; - iov.iov_len = 0; - - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - recvl = recvmsg(net_sock, &msg, MSG_PEEK | MSG_TRUNC); - if (recvl < 0) { - err = errno; - eprintf("Error in get length recvmsg(), errno %d\n", err); - errno = err; - return -1; - } -#ifdef PRINTLOGS - printf("received len %d\n",recvl); -#endif - return recvl; + fprintf(fp, "Interface name %s\n", ifs->ifname); + fprintf(fp, "rx_packets %llu\n", ifs->st64.rx_packets); + fprintf(fp, "tx_packets %llu\n", ifs->st64.tx_packets); + fprintf(fp, "rx_bytes %llu\n", ifs->st64.rx_bytes); + fprintf(fp, "tx_bytes %llu\n", ifs->st64.tx_bytes); } -static int get_max_ifaces(int len) +void print_if(struct ifstats *ifs) { - int header_size, max_if; - - header_size = (sizeof(struct nlmsghdr)) + - (sizeof(struct if_stats_msg)) + - (sizeof(struct rtnl_link_stats64)); -#ifdef PRINTLOGS - printf("header_size %d len %d\n",header_size, len); -#endif - max_if = len/header_size; - return max_if; -} - -static int handle_stats_resp(int net_sock, void **out) -{ - int err, recvl, len, max_ifs, if_size; - int ifind = 0, total_if_size = 0; - struct iovec iov; - struct msghdr msg; - struct nlmsghdr *r; - struct nlmsgerr *nlmsg_err; - struct if_stats_msg *ifsm; - struct rtattr *at[IFLA_STATS_MAX+1]; - struct rtattr *rta; - struct ifstats *ifaces = NULL, *ifs = NULL; - struct sockaddr_nl nladdr; - - msg.msg_name = &nladdr; - msg.msg_namelen = sizeof(nladdr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - while(1) { - len = get_if_len(net_sock); - if (len == -1) { - if (ifaces) - free(ifaces); - return -1; - } - char *buf = (char *)malloc(len); - if (!buf) { - if (ifaces) - free(ifaces); - return -1; - } - iov.iov_base = buf; - iov.iov_len = len; - max_ifs = get_max_ifaces(len); - if_size = max_ifs * sizeof(struct ifstats); - total_if_size += if_size; -#ifdef PRINTLOGS - printf("max_ifs %d, if_size %d total_if_size %d\n",max_ifs, if_size, total_if_size); -#endif - void *tmp = (struct ifstats *) realloc(ifaces, total_if_size); - if (!tmp) { - if (ifaces) - free(ifaces); - free(buf); - return -1; - } - ifaces = tmp; - ifs = ifaces + ifind; - - recvl = recvmsg(net_sock, &msg, 0); - if (recvl < 0) { - err = errno; - free(ifaces); - free(buf); - eprintf("Error in response recvmsg(), errno %d\n", err); - errno = err; - return -1; - } -#ifdef PRINTLOGS - printf("received len %d\n",recvl); -#endif - r = (struct nlmsghdr *) buf; - while (NLMSG_OK(r, recvl)) { - if (r->nlmsg_type == NLMSG_ERROR) { - nlmsg_err = (struct nlmsgerr *)NLMSG_DATA(r); - eprintf("NLMSG_ERROR error: %d\n", - nlmsg_err->error); - ecount++; - free(buf); - free(ifaces); - errno = nlmsg_err->error; - return -1; - } else if (r->nlmsg_type == NLMSG_DONE) { -#ifdef PRINTLOGS - printf("DONE\n"); -#endif - free(buf); - *(struct ifstats **)out = ifaces; - return ifind; - } - ifsm = NLMSG_DATA(r); - len = r->nlmsg_len; -#ifdef PRINTLOGS - printf("r->nlmsg_type is %d\n", r->nlmsg_type); - printf("Received if_stats_msg, len %d\n", len); - printf("ifindex is %d\n", ifsm->ifindex); -#endif - len -= NLMSG_LENGTH(sizeof(*ifsm)); - if (len < 0) { - eprintf("nlmsg_len incorrect"); - errno = EINVAL; - free(buf); - free(ifaces); - return -1; - } -#ifdef PRINTLOGS - printf("len after sub %lu is %d\n",sizeof(*ifsm), len); -#endif - rta = ((struct rtattr *)(((char *)(ifsm)) + NLMSG_ALIGN(sizeof(struct if_stats_msg)))); - parse_attr(at, rta, len); - memcpy(&ifs->st64, RTA_DATA(at[IFLA_STATS_LINK_64]), sizeof(*ifs)); - if (if_indextoname(ifsm->ifindex, ifs->ifname) == NULL) - eprintf("Error in if_indextoname %d\n",errno); -#ifdef PRINTLOGS - else - printf("Interface name %s\n",ifs->ifname); - printf("rx_packets %llu\n",ifs->st64.rx_packets); - printf("tx_packets %llu\n",ifs->st64.tx_packets); - printf("rx_bytes %llu\n",ifs->st64.rx_bytes); - printf("tx_bytes %llu\n",ifs->st64.tx_bytes); -#endif - ifs++; - ifind++; - r = NLMSG_NEXT(r, recvl); - count++; - } - free(buf); -#ifdef PRINTLOGS - printf("No. of interfaces: %d\n",ifind); -#endif - } - *(struct ifstats **)out = ifaces; - return ifind; + printf("Interface name %s\n", ifs->ifname); + printf("rx_packets %llu\n", ifs->st64.rx_packets); + printf("tx_packets %llu\n", ifs->st64.tx_packets); + printf("rx_bytes %llu\n", ifs->st64.rx_bytes); + printf("tx_bytes %llu\n", ifs->st64.tx_bytes); } int get_net_dev(void **out) { int err, net_sock; - net_sock = connect_dev(); - if (net_sock == -1) - return -1; + + net_sock = connect_netlink(0); + if (net_sock < 0) + return net_sock; + err = send_stats_req(net_sock); - if (err == -1) { + if (err < 0) { close(net_sock); - return -1; + return err; } - err = handle_stats_resp(net_sock, out); - if (err == -1) { - close(net_sock); - return -1; - } -#ifdef PRINTLOGS - printf("count %d error count %d\n",count, ecount); -#endif + err = handle_net_resp(NET_IF, net_sock, out); + close(net_sock); return err; } @@ -289,8 +104,7 @@ int getdevinfo(int res_id, void *out, size_t sz, void **hint, int flags) break; default: eprintf("Resource Id is invalid"); - errno = EINVAL; - return -1; + return -EINVAL; } return len; } diff --git a/net_route.c b/net_route.c index 50d7d2c..ba45b56 100644 --- a/net_route.c +++ b/net_route.c @@ -16,32 +16,8 @@ #include #include #include "resource_impl.h" +#include "net.h" -static int count, ecount; - -static int connect_route() -{ - struct sockaddr_nl nl_saddr; - int err, net_sock; - - net_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (net_sock == -1) { - err = errno; - eprintf("Error in socket(), errno %d\n", err); - return -err; - } - bzero(&nl_saddr, sizeof(nl_saddr)); - nl_saddr.nl_family = AF_NETLINK; - err = bind(net_sock, (struct sockaddr *)&nl_saddr, sizeof(nl_saddr)); - if (err == -1) { - err = errno; - eprintf("Error in bind(), errno %d\n", err); - close(net_sock); - return -err; - } - return net_sock; -} - static int send_route_req(int net_sock) { int err; @@ -108,7 +84,7 @@ static inline const char *proto_str(int proto) } } -static void print_rt_info(struct rt_info *rt, FILE *fp) +void print_rt_info(struct rt_info *rt, FILE *fp) { char ifname[IF_NAMESIZE]; @@ -140,7 +116,7 @@ static void print_rt_info(struct rt_info *rt, FILE *fp) } #endif -static int get_attr(struct rtattr *at[], struct rt_info *rt, struct rtmsg *m) +int get_rt_attr(struct rtattr *at[], struct rt_info *rt, struct rtmsg *m) { bzero(rt, sizeof(*rt)); rt->family = m->rtm_family; @@ -188,7 +164,7 @@ static int get_attr(struct rtattr *at[], struct rt_info *rt, struct rtmsg *m) return 0; } -static int parse_attr(struct rtattr *at[], struct rtattr *rta, int len) +int parse_rt_attr(struct rtattr *at[], struct rtattr *rta, int len) { memset(at, 0, sizeof(struct rtattr *) * (RTA_MAX + 1)); while (RTA_OK(rta, len)) { @@ -199,202 +175,21 @@ static int parse_attr(struct rtattr *at[], struct rtattr *rta, int len) return 0; } -static int get_route_len(int net_sock) -{ - int recvl, err; - struct msghdr msg; - struct iovec iov; - struct sockaddr_nl nladdr; - - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - msg.msg_name = &nladdr; - msg.msg_namelen = sizeof(nladdr); - iov.iov_base = NULL; - iov.iov_len = 0; - - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - recvl = recvmsg(net_sock, &msg, MSG_PEEK | MSG_TRUNC); - if (recvl < 0) { - err = errno; - eprintf("Error in get length recvmsg(), errno %d\n", err); - return -err; - } -#ifdef PRINTLOGS - printf("received len %d\n",recvl); -#endif - return recvl; -} - -static int get_max_routes(int len) -{ - int header_size, max_routes; - - header_size = (sizeof(struct nlmsghdr)) + (sizeof(struct rtmsg)); - max_routes = len/header_size; - return max_routes; -} - -static int handle_route_resp(int net_sock, void **out) +void print_rt(struct rtmsg *rt) { - int recvl, len, max_routes, rt_size; - int rtind = 0, total_rt_size = 0; - struct iovec iov; - struct msghdr msg; - struct nlmsghdr *r; - struct nlmsgerr *nlmsg_err; - struct rtmsg *rt; - struct rtattr *at[RTA_MAX + 1]; - struct rt_info *routes = NULL, *iroutes = NULL; - struct sockaddr_nl nladdr; - unsigned int family; - int ret = 0; - -#ifdef TESTING - FILE *fp; - fp = fopen("./route_info.txt", "w"); - if (!fp) { - eprintf("Error opening file route_info.txt with errno: %d", errno); - return -1; - } -#endif - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &nladdr; - msg.msg_namelen = sizeof(nladdr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - while(1) { - len = get_route_len(net_sock); - if (len < 0) { - if (routes) - free(routes); - ret = len; - goto out; - } - char *buf = (char *)malloc(len); - if (!buf) { - if (routes) - free(routes); - ret = -ENOMEM; - goto out; - } - memset(&iov, 0, sizeof(iov)); - iov.iov_base = buf; - iov.iov_len = len; - max_routes = get_max_routes(len); - rt_size = max_routes * sizeof(struct rt_info); - total_rt_size += rt_size; - - void *tmp = (struct rt_info *) realloc(routes, total_rt_size); - if (!tmp) { - if (routes) - free(routes); - free(buf); - ret = -ENOMEM; - goto out; - } - routes = tmp; - iroutes = routes + rtind; - - recvl = recvmsg(net_sock, &msg, 0); - if (recvl < 0) { - ret = -errno; - free(routes); - free(buf); - eprintf("Error in response recvmsg(), errno %d\n", -ret); - goto out; - } -#ifdef PRINTLOGS - printf("received len %d\n",recvl); -#endif - r = (struct nlmsghdr *) buf; - while (NLMSG_OK(r, recvl)) { - if (r->nlmsg_type == NLMSG_ERROR) { - nlmsg_err = (struct nlmsgerr *)NLMSG_DATA(r); - eprintf("NLMSG_ERROR error: %d\n", - nlmsg_err->error); - ecount++; - free(buf); - free(routes); - ret = -(nlmsg_err->error); - goto out; - } else if (r->nlmsg_type == NLMSG_DONE) { -#ifdef PRINTLOGS - printf("DONE\n"); -#endif - free(buf); - *(struct rt_info **)out = routes; - ret = rtind; - goto out; - } - rt = (struct rtmsg *)NLMSG_DATA(r); - len = r->nlmsg_len; -#ifdef PRINTLOGS - printf("r->nlmsg_type is %d (RTM_NEWROUTE = 24)\n", r->nlmsg_type); - printf("Received rtmsg, len %d\n", len); - printf("family: %hhu\n", rt->rtm_family); - printf("rtm_dst_len %hhu\n",rt->rtm_dst_len); - printf("rtm_src_len %hhu\n",rt->rtm_src_len); - printf("rtm_type: %hhu\n", rt->rtm_type); - printf("rtm_flags: %u\n",rt->rtm_flags); - printf("rtm_protocol: %hhu\n",rt->rtm_protocol); -#endif - len -= NLMSG_LENGTH(sizeof(*rt)); - if (len < 0) { - eprintf("nlmsg_len incorrect"); - free(buf); - free(routes); - ret = -EINVAL; - goto out; - } -#ifdef PRINTLOGS - printf("len after sub %lu is %d\n",sizeof(*rt), len); -#endif - parse_attr(at, RTM_RTA(rt), len); - family = rt->rtm_family; - if (family == AF_INET || family == AF_INET6) { - if ((rt->rtm_type == RTN_BROADCAST) || - (rt->rtm_type == RTN_MULTICAST) || - (rt->rtm_type == RTN_LOCAL)) { - r = NLMSG_NEXT(r, recvl); - continue; - } - - get_attr(at, iroutes, rt); -#ifdef TESTING - print_rt_info(iroutes, fp); -#endif - iroutes++; - rtind++; - } - r = NLMSG_NEXT(r, recvl); - count++; - } - free(buf); -#ifdef PRINTLOGS - printf("No. of routes: %d\n",rtind); -#endif - } - *(struct rt_info **)out = routes; - ret = rtind; -out: -#ifdef TESTING - if (fp) - fclose(fp); -#endif - return ret; + printf("family: %hhu\n", rt->rtm_family); + printf("rtm_dst_len %hhu\n",rt->rtm_dst_len); + printf("rtm_src_len %hhu\n",rt->rtm_src_len); + printf("rtm_type: %hhu\n", rt->rtm_type); + printf("rtm_flags: %u\n",rt->rtm_flags); + printf("rtm_protocol: %hhu\n",rt->rtm_protocol); } int get_net_route(void **out) { int err, net_sock; - net_sock = connect_route(); + net_sock = connect_netlink(0); if (net_sock < 0) return net_sock; @@ -404,7 +199,7 @@ int get_net_route(void **out) return err; } - err = handle_route_resp(net_sock, out); + err = handle_net_resp(NET_ROUTE, net_sock, out); close(net_sock); return err; } @@ -420,8 +215,7 @@ int getrouteinfo(int res_id, void *out, size_t sz, void **hint, int flags) break; default: eprintf("Resource Id is invalid"); - errno = EINVAL; - return -1; + return -EINVAL; } return len; } diff --git a/resource.c b/resource.c index ad7e67d..bf4a3f5 100644 --- a/resource.c +++ b/resource.c @@ -196,7 +196,7 @@ int res_read(int res_id, void *out, size_t out_sz, void **hint, int pid, int fla return getmeminfo(res_id, out, out_sz, hint, pid, flags); #endif - if (res_id >= NET_MIN && res_id < NET_MAX) + if (res_id >= RES_NET_MIN && res_id < RES_NET_MAX) return getnetinfo(res_id, out, out_sz, hint, pid, flags); if (res_id >= VM_MIN && res_id < VM_MAX) diff --git a/resource.h b/resource.h index 9e86a3f..66110a3 100644 --- a/resource.h +++ b/resource.h @@ -105,7 +105,7 @@ typedef struct res_blk { #define RES_NET_DEV_ALL 2022 #define DEV_MAX 2030 -#define NET_MIN 2048 +#define RES_NET_MIN 2048 #define RES_NET_IFSTAT 2049 #define RES_NET_ALLIFSTAT 2050 #define RES_NET_IP_LOCAL_PORT_RANGE 2051 @@ -113,7 +113,7 @@ typedef struct res_blk { #define RES_NET_TCP_WMEM_MAX 2053 #define RES_NET_RMEM_MAX 2054 #define RES_NET_WMEM_MAX 2055 -#define NET_MAX 2051 +#define RES_NET_MAX 2051 #define KERN_MIN 3072 #define RES_KERN_COMPILE_TIME 3073 diff --git a/tests/ARP/arp_test.c b/tests/ARP/arp_test.c index 8aa4efd..ec5bfaf 100644 --- a/tests/ARP/arp_test.c +++ b/tests/ARP/arp_test.c @@ -28,7 +28,8 @@ int main(int argc, char **argv) struct arp_info *arp = NULL, *arpn; narps = res_read(RES_NET_ARP_ALL, NULL, 0, (void **)&arp, 0, 0); - if (narps == -1) { + if (narps < 0) { + printf("res_read() returned %d\n", narps); exit(1); } arpn = arp; diff --git a/tests/IF/if.sh b/tests/IF/if.sh new file mode 100755 index 0000000..3ad1978 --- /dev/null +++ b/tests/IF/if.sh @@ -0,0 +1,8 @@ +# Enable -DTESTING in Makefile and the recompile library - make +export LD_LIBRARY_PATH=`git rev-parse --show-toplevel` +cd $LD_LIBRARY_PATH +cd tests/IF +rm -f ./if_test +rm -f ./if_info.txt +cc -I $LD_LIBRARY_PATH -std=gnu99 -o if_test if_test.c -L $LD_LIBRARY_PATH -lresource +./if_test diff --git a/tests/IF/if_test.c b/tests/IF/if_test.c new file mode 100644 index 0000000..12b7ec8 --- /dev/null +++ b/tests/IF/if_test.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int intfs; + struct ifstats *ifs = NULL, *ifsn; + + intfs = res_read(RES_NET_DEV_ALL, NULL, 0, (void **)&ifs, 0, 0); + if (intfs < 0) { + printf("res_read() returned %d\n", intfs); + exit(1); + } + ifsn = ifs; + printf("No. of interfaces: %d\n",intfs); + for (int i = 0; i < intfs; i++) { + printf("Interface %s\n", ifs->ifname); + printf("rx_packets %llu\n",ifs->st64.rx_packets); + printf("tx_packets %llu\n",ifs->st64.tx_packets); + printf("rx_bytes %llu\n",ifs->st64.rx_bytes); + printf("tx_bytes %llu\n",ifs->st64.tx_bytes); + ifs++; + } + if (ifsn) + free(ifsn); +} diff --git a/tests/ROUTE/route_test.c b/tests/ROUTE/route_test.c index af8d0b4..e59c607 100644 --- a/tests/ROUTE/route_test.c +++ b/tests/ROUTE/route_test.c @@ -28,7 +28,8 @@ int main(int argc, char **argv) struct rt_info *rt = NULL, *rtn; nroutes = res_read(RES_NET_ROUTE_ALL, NULL, 0, (void **)&rt, 0, 0); - if (nroutes == -1) { + if (nroutes < 0) { + printf("res_read() returned %d\n", nroutes); exit(1); } rtn = rt; diff --git a/tests/STAT/stat_test.c b/tests/STAT/stat_test.c index cc54b05..21ae872 100644 --- a/tests/STAT/stat_test.c +++ b/tests/STAT/stat_test.c @@ -34,8 +34,10 @@ int main(int argc, char **argv) size = sizeof(struct cpu_stat) * cpu_num; stats.all_cpu = (struct cpu_stat *) malloc(size); err = res_read(RES_STAT_INFO, &stats, sizeof(stats)+size, NULL, 0, 0); - if (err != 0) - printf("err is %d\n",err); + if (err != 0) { + printf("res_read() err is %d\n",err); + exit(1); + } st = &stats; fp = fopen ("./stat_info.txt", "w"); if (fp == NULL) {