From 5bd570df4d9d9589b169ed9a5629c8874fe60314 Mon Sep 17 00:00:00 2001 From: libin-n-g Date: Thu, 22 Jun 2017 12:15:03 +0530 Subject: [PATCH 1/7] Add net_connections --- driver.c | 162 ++++++++++---- pslib.h | 45 ++++ pslib_linux.c | 589 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 749 insertions(+), 47 deletions(-) diff --git a/driver.c b/driver.c index e433e0c..78aa6e7 100644 --- a/driver.c +++ b/driver.c @@ -10,11 +10,11 @@ void test_diskusage() { printf(" -- disk_usage \n"); disk_usage("/", &du); printf("/\ntotal: %" PRIu64 "\nused: %" PRIu64 "\nfree: %" PRIu64 - "\npercent: %f\n\n", + "\npercent: %.1f\n\n", du.total, du.used, du.free, du.percent); disk_usage("/etc", &du); printf("/etc\ntotal: %" PRIu64 "\nused: %" PRIu64 "\nfree: %" PRIu64 - "\npercent: %f\n\n", + "\npercent: %.1f\n\n", du.total, du.used, du.free, du.percent); } @@ -139,7 +139,7 @@ void test_virtualmeminfo() { printf(" -- virtual_memory\n"); printf("Total: %" PRIu64 "\n", r.total); printf("Available: %" PRIu64 "\n", r.available); - printf("Percent: %f\n", r.percent); + printf("Percent: %.1f\n", r.percent); printf("Used: %" PRIu64 "\n", r.used); printf("Free: %" PRIu64 "\n", r.free); printf("Active: %" PRIu64 "\n", r.active); @@ -160,7 +160,7 @@ void test_swap() { printf("Total: %" PRIu64 "\n", r.total); printf("Used: %" PRIu64 "\n", r.used); printf("Free: %" PRIu64 "\n", r.free); - printf("Percent: %f\n", r.percent); + printf("Percent: %.1f\n", r.percent); printf("Sin: %" PRIu64 "\n", r.sin); printf("Sout: %" PRIu64 "\n", r.sout); printf("\n"); @@ -174,16 +174,16 @@ void test_cpu_times() { return; } printf(" -- cpu_times\n"); - printf("User: %.3lf;", r->user); - printf(" Nice: %.3lf;", r->nice); - printf(" System: %.3lf;", r->system); - printf(" Idle: %.3lf;", r->idle); - printf(" IOWait: %.3lf;", r->iowait); - printf(" IRQ: %.3lf;", r->irq); - printf(" SoftIRQ: %.3lf;", r->softirq); - printf(" Steal: %.3lf;", r->steal); - printf(" Guest: %.3lf;", r->guest); - printf(" Guest nice: %.3lf\n", r->guest_nice); + printf("User: %.1lf;", r->user); + printf(" Nice: %.1lf;", r->nice); + printf(" System: %.1lf;", r->system); + printf(" Idle: %.1lf;", r->idle); + printf(" IOWait: %.1lf;", r->iowait); + printf(" IRQ: %.1lf;", r->irq); + printf(" SoftIRQ: %.1lf;", r->softirq); + printf(" Steal: %.1lf;", r->steal); + printf(" Guest: %.1lf;", r->guest); + printf(" Guest nice: %.1lf\n", r->guest_nice); printf("\n\n"); free(r); @@ -200,16 +200,16 @@ void test_cpu_times_percpu() { printf(" -- cpu_times_percpu\n"); for (uint32_t i = 0; i < ncpus; i++) { printf("CPU %" PRIu32 " :: ", i + 1); - printf(" Usr: %.3lf;", c->user); - printf(" Nice: %.3lf;", c->nice); - printf(" Sys: %.3lf;", c->system); - printf(" Idle: %.3lf;", c->idle); - printf(" IOWait: %.3lf;", c->iowait); - printf(" IRQ: %.3lf;", c->irq); - printf(" SoftIRQ: %.3lf;", c->softirq); - printf(" Steal: %.3lf;", c->steal); - printf(" Guest: %.3lf;", c->guest); - printf(" Guest nice: %.3lf\n", c->guest_nice); + printf(" Usr: %.1lf;", c->user); + printf(" Nice: %.1lf;", c->nice); + printf(" Sys: %.1lf;", c->system); + printf(" Idle: %.1lf;", c->idle); + printf(" IOWait: %.1lf;", c->iowait); + printf(" IRQ: %.1lf;", c->irq); + printf(" SoftIRQ: %.1lf;", c->softirq); + printf(" Steal: %.1lf;", c->steal); + printf(" Guest: %.1lf;", c->guest); + printf(" Guest nice: %.1lf\n", c->guest_nice); printf("\n"); c++; } @@ -230,7 +230,7 @@ void test_cpu_util_percent() { usleep(100000); utilisation = cpu_util_percent(false, info); printf(" -- cpu_util_percent\n"); - printf("%f\n", *utilisation); + printf("%.1f\n", *utilisation); printf("\n"); free(utilisation); @@ -252,7 +252,7 @@ void test_cpu_util_percent_percpu() { percentages = cpu_util_percent(1, info); printf(" -- cpu_util_percent_percpu\n"); for (uint32_t i = 0; i < ncpus; i++) { - printf("Cpu #%" PRIu32 " : %f\n", i, percentages[i]); + printf("Cpu #%" PRIu32 " : %.1f\n", i, percentages[i]); } printf("\n"); @@ -277,16 +277,16 @@ void test_cpu_times_percent() { } printf(" -- cpu_times_percent\n"); printf("CPU times as percentage of total (0.1 second sample)\n"); - printf("Usr: %.3lf;", ret->user); - printf(" Nice: %.3lf;", ret->nice); - printf(" Sys: %.3lf;", ret->system); - printf(" Idle: %.3lf;", ret->idle); - printf(" IOWait: %.3lf;", ret->iowait); - printf(" IRQ: %.3lf;", ret->irq); - printf(" SoftIRQ: %.3lf;", ret->softirq); - printf(" Steal: %.3lf;", ret->steal); - printf(" Guest: %.3lf;", ret->guest); - printf(" Guest nice: %.3lf\n", ret->guest_nice); + printf("Usr: %.1lf;", ret->user); + printf(" Nice: %.1lf;", ret->nice); + printf(" Sys: %.1lf;", ret->system); + printf(" Idle: %.1lf;", ret->idle); + printf(" IOWait: %.1lf;", ret->iowait); + printf(" IRQ: %.1lf;", ret->irq); + printf(" SoftIRQ: %.1lf;", ret->softirq); + printf(" Steal: %.1lf;", ret->steal); + printf(" Guest: %.1lf;", ret->guest); + printf(" Guest nice: %.1lf\n", ret->guest_nice); printf("\n"); free(info); free(ret); @@ -312,16 +312,16 @@ void test_cpu_times_percent_percpu() { printf("CPU times as percentage of total per CPU (0.1 second sample)\n"); for (uint32_t i = 0; i < ncpus; i++) { printf("CPU %" PRIu32 " :: ", i + 1); - printf("Usr: %.3lf;", info->user); - printf(" Nice: %.3lf;", info->nice); - printf(" Sys: %.3lf;", info->system); - printf(" Idle: %.3lf;", info->idle); - printf(" IOWait: %.3lf;", info->iowait); - printf(" IRQ: %.3lf;", info->irq); - printf(" SoftIRQ: %.3lf;", info->softirq); - printf(" Steal: %.3lf;", info->steal); - printf(" Guest: %.3lf;", info->guest); - printf(" Guest nice: %.3lf\n", info->guest_nice); + printf("Usr: %.1lf;", info->user); + printf(" Nice: %.1lf;", info->nice); + printf(" Sys: %.1lf;", info->system); + printf(" Idle: %.1lf;", info->idle); + printf(" IOWait: %.1lf;", info->iowait); + printf(" IRQ: %.1lf;", info->irq); + printf(" SoftIRQ: %.1lf;", info->softirq); + printf(" Steal: %.1lf;", info->steal); + printf(" Guest: %.1lf;", info->guest); + printf(" Guest nice: %.1lf\n", info->guest_nice); info++; } @@ -376,6 +376,75 @@ void test_process() { free_process(process); } +void test_net_connections() +{ + char *status[] ={"ESTABLISHED","SYN_SENT","SYN_RECV","FIN_WAIT1","FIN_WAIT2","TIME_WAIT", + "CLOSE", + "CLOSE_WAIT", + "LAST_ACK", + "LISTEN", + "CLOSING", + "NONE", + "DELETE_TCB", + "IDLE", + "BOUND" + }; + printf("\nnet_connections\n"); + ConnInfo *result; + char *array[] ={"all", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "unix", "inet", "inet4", "inet6"}; + int i=0,j=0; + for(j=0;j < 11;j++) + { + i=0; + + result = net_connections(array[j]); + printf("\n%s\n",array[j]); + if(result) + { + while(i < (int)result->nitems) + { + printf("fd=%d, family=%d, type=%d,",result->Connections[i].fd,result->Connections[i].family,result->Connections[i].type); + if(!(strcmp(result->Connections[i].laddr->ip, "NONE"))) + { + printf(" laddr=(),"); + } + else if((result->Connections[i].laddr->port == -1)) + { + printf(" laddr='%s',",result->Connections[i].laddr->ip); + } + else + { + printf(" laddr=('%s', %d),",result->Connections[i].laddr->ip,result->Connections[i].laddr->port); + } + if(!(strcmp(result->Connections[i].raddr->ip, "NONE"))) + { + printf(" raddr=(),"); + } + else if(result->Connections[i].laddr->port == -1) + { + printf(" raddr='%s',",result->Connections[i].raddr->ip); + } + else + { + printf(" raddr=('%s', %d),",result->Connections[i].raddr->ip,result->Connections[i].raddr->port); + } + printf(" status='%s',", status[result->Connections[i].status]); + if(result->Connections[i].pid==-1) + { + printf(" pid=None\n"); + } + else + { + printf(" pid=%d\n", result->Connections[i].pid); + } + i++; + } + + } + free_ConnInfo(result); + } +} + int main(void) { test_diskusage(); test_diskpartitioninfo(); @@ -398,4 +467,5 @@ int main(void) { test_cpu_count(); test_pid_exists(); test_process(); + test_net_connections(); } diff --git a/pslib.h b/pslib.h index 538d1c7..c932221 100644 --- a/pslib.h +++ b/pslib.h @@ -4,6 +4,7 @@ #include #include + enum proc_status { STATUS_RUNNING, STATUS_SLEEPING, @@ -188,6 +189,46 @@ typedef struct { char *terminal; } Process; +//for storing list of pids +typedef struct { + pid_t *pid; + int size; +} Pidlist; +// structure to store ip address +typedef struct{ + char ip[500]; + int port; +}address ; +//stores details of connections +typedef struct{ + int fd; + int family; + int type; + address *laddr; + address *raddr; + enum con_status status; + pid_t pid; +}Conn; + +typedef struct{ + uint32_t nitems; + Conn * Connections; +} ConnInfo; +//structure for storing famiy and type for each kind of connections +typedef struct{ + char name[7]; + int family; + int type_; +} Connection; +// structure for storing list of pid and fd for each inode +typedef struct i_nodes{ + int inode; + struct i_nodes *Next_in_list; + struct i_nodes *Next_collision; /* to manage collision as hashing is implemented */ + pid_t pid; + int fd; +} Inodes; + bool disk_usage(const char[], DiskUsage *); DiskPartitionInfo *disk_partitions(bool); @@ -220,8 +261,12 @@ bool pid_exists(pid_t); Process *get_process(pid_t); void free_process(Process *); +ConnInfo *net_connections(char kind[]); +void free_ConnInfo(ConnInfo *); + /* Required to avoid [-Wimplicit-function-declaration] for python bindings */ void gcov_flush(void); // disk_io_counters_per_disk // net_io_counters_per_nic + diff --git a/pslib_linux.c b/pslib_linux.c index 60505f1..22937de 100644 --- a/pslib_linux.c +++ b/pslib_linux.c @@ -12,10 +12,16 @@ #include #include #include +#include +#include +#include + #include "pslib.h" #include "common.h" +#define HASHSIZE 2731 + void __gcov_flush(void); static int clean_cmdline(char *ip, int len) @@ -306,6 +312,7 @@ static double get_create_time(pid_t pid) { FILE *fp = NULL; char procfile[50]; char s_pid[10]; + char *tmp; double ct_jiffies; double ct_seconds; double clock_ticks = sysconf(_SC_CLK_TCK); @@ -315,7 +322,9 @@ static double get_create_time(pid_t pid) { sprintf(procfile, "/proc/%d/stat", pid); fp = fopen(procfile, "r"); check(fp, "Couldn't open process stat file"); - ct_jiffies = atof(grep_awk(fp, s_pid, 21, " ")); + tmp = grep_awk(fp, s_pid, 21, " "); + ct_jiffies = atof(tmp); + free(tmp); fclose(fp); ct_seconds = boot_time + (ct_jiffies / clock_ticks); return ct_seconds; @@ -1110,6 +1119,584 @@ void free_process(Process *p) { free(p->terminal); free(p); } +// NET CONNECTIONS + + +Connection tcp4 = {"tcp", AF_INET, SOCK_STREAM}; +Connection tcp6 = {"tcp6", AF_INET6, SOCK_STREAM}; +Connection udp4 = {"udp", AF_INET, SOCK_DGRAM}; +Connection udp6 = {"udp6", AF_INET6, SOCK_DGRAM}; +Connection Unix = {"unix", AF_UNIX, 0}; + +const struct{ + const char* kind_label[12]; + const Connection *kind[11][6]; +} tmap = {{"all", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "unix", "inet", "inet4", "inet6", '\0'}, + {{&tcp4,&tcp6, &udp4, &udp6, &Unix, NULL}, + {&tcp4, &tcp6, NULL}, + {&tcp4, NULL}, + {&tcp6, NULL}, + {&udp4, &udp6, NULL}, + {&udp4, NULL}, + {&udp6, NULL}, + {&Unix, NULL}, + {&tcp4, &tcp6, &udp4, &udp6, NULL}, + {&tcp4, &udp4, NULL}, + {&tcp6, &udp6, NULL}} + }; + + + +bool IsSame(Conn *a,Conn *b) +{ + if((a->family==b->family) && (a->fd==b->fd) && (a->pid==b->pid) && (a->status==b->status) && (a->type==b->type)) + { + if((!strcmp(a->laddr->ip,b->laddr->ip)) && (!strcmp(a->raddr->ip,b->raddr->ip)) && (a->raddr->port == b->raddr->port) && (a->laddr->port==b->laddr->port)) + { + return true; + } + } + return false; +} + +int isnumber(char c[]) +{ + int i = 0; + for (i=0;c[i]!='\0';i++) + { + if (!isdigit(c[i])) + return 0; + } + return 1; +} +// Returns list of all PIDs +Pidlist *pids() +{ + DIR *d; + Pidlist *ret; + struct dirent *dir; + ret = (Pidlist*)calloc(1,sizeof(Pidlist)); + check_mem(ret); + ret->pid = (pid_t*)calloc(1,sizeof(pid_t)); + check_mem(ret->pid); + ret->size = 1; + d = opendir("/proc"); + check_mem(d); + while ((dir = readdir(d)) != NULL) + { + if(sscanf(dir->d_name,"%"PRId32, &ret->pid[ret->size-1])) + { + ret->size++; + } + if(ret->size > 1) + ret->pid = (pid_t*)realloc(ret->pid,(ret->size)*sizeof(pid_t)); + } + closedir(d); + return ret; + error: + if(ret) + { + if(ret->pid) + { + free(ret->pid); + } + free(ret); + } + if(d) + { + closedir(d); + } + return NULL; +} + +Inodes *get_proc_inodes(pid_t pid) +{ + DIR *d; + struct dirent *dir; + Inodes *inodes = NULL; + char filepath[500]; + char link[500]; + char fdpath[500]; + int inode, len, no=0; + inodes = (Inodes *)calloc(1,sizeof(Inodes)); + check_mem(inodes); + snprintf(fdpath, sizeof(fdpath), "/proc/%"PRId32"/fd", pid); + d = opendir(fdpath); + if(d)/*Error is ignored as we could get a lot of permission denied*/ + { + while ((dir = readdir(d)) != NULL) + { + if ( (strcmp(dir->d_name, ".") != 0) && (strcmp(dir->d_name, "..")!= 0) ) + { + snprintf(filepath, sizeof(filepath), "%s/%s", fdpath, dir->d_name); + len = readlink(filepath,link,500); + check((len!=-1),"readlink error\n"); + link[len] = '\0'; + if (sscanf(link, "socket:[%d]", &inode)) + { + sscanf(dir->d_name, "%d", &(inodes[no].fd)); + inodes[no].inode = inode; + inodes[no].pid = pid; + inodes[no].Next_collision = NULL; + inodes[no].Next_in_list = NULL; + no++; + if(no > 0) + { + inodes = (Inodes*)realloc(inodes,(no+1)*sizeof(Inodes)); + check_mem(inodes); + } + } + } + } + closedir(d); + } + inodes[no].inode = -1; + inodes[no].pid = -1; + inodes[no].fd = -1; + inodes[no].Next_collision = NULL; + inodes[no].Next_in_list = NULL; + return inodes; + error: + if(d) + { + closedir(d); + } + if(inodes) + { + free(inodes); + } + return NULL; +} +//function which calcultes key for Hash table from inode +unsigned long hashfunction(int inode) +{ + unsigned int hash = HASHSIZE; + hash = (inode ^ hash )% hash; + return hash; +} +//function to update hash table by inserting lselement to inodes +Inodes *Update(Inodes *ls_element, Inodes *inodes) +{ + Inodes *tmp; + if(inodes == NULL) + { + inodes = ls_element; + } + else if(inodes->inode == ls_element->inode) + { + if(inodes->pid == ls_element->pid) + { + ls_element->Next_in_list = inodes; + inodes = ls_element; + } + else + { + tmp = inodes->Next_collision; + inodes = ls_element; + ls_element->Next_collision = tmp; + } + } + else + { + inodes->Next_collision = Update(ls_element,inodes->Next_collision); + } + return inodes; +} + +Inodes **get_all_inodes() +{ + Inodes **inodes = NULL, *ls=NULL; + Pidlist *PID; + int i,j=0,index=0; + inodes = (Inodes **)calloc(HASHSIZE, sizeof(Inodes*)); + check_mem(inodes); + PID = pids(); + for(i = 0; i < PID->size ;i++ ) + { + ls = get_proc_inodes(PID->pid[i]); + for(j=0;ls[j].inode != -1;j++) + { + index = hashfunction(ls[j].inode); + inodes[index]=Update(&ls[j],inodes[index]); + } + } + return inodes; + error: + return NULL; +} +/* convert IPv6 address to human readable form like + * "0500000A:0016" -> ("10.0.0.5", 22) */ +address *decodeIPv4(char Addr[],address *Address) +{ + /* TODO : changing byte order with respect to endian*/ + uint32_t IP; + sscanf(Addr, "%"SCNx32":%x", &IP, &(Address->port)); + const struct in_addr naddr4 = {IP}; + const char *tmp = inet_ntop(AF_INET,&naddr4, Address->ip, 150); + check(tmp,"decode of IPv4 failed\n"); + return Address; + error: + return NULL; +} +/* convert IPv6 address to human readable form like + * "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)*/ +address *decodeIPv6(char Addr[], address *Address) +{ + /* TODO : changing byte order with respect to endian*/ + uint8_t int_ip[16]; + sscanf(Addr, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx:%x", + &int_ip[0], &int_ip[1], &int_ip[2], &int_ip[3], + &int_ip[4], &int_ip[5], &int_ip[6], &int_ip[7], + &int_ip[8], &int_ip[9], &int_ip[10], &int_ip[11], + &int_ip[12], &int_ip[13], &int_ip[14], &int_ip[15],&(Address->port)); + const struct in6_addr naddr6 = {{{(int_ip[3]),(int_ip[2]),(int_ip[1]),int_ip[0], + int_ip[7],int_ip[6],int_ip[5],int_ip[4], + int_ip[11],int_ip[10],int_ip[9],int_ip[8], + int_ip[15],int_ip[14],int_ip[13],int_ip[12]}}}; + const char *tmp = inet_ntop(AF_INET6,&naddr6,(Address->ip),150); + check(tmp,"decode of IPv6 failed\n"); + return Address; + error: + return NULL; +} +/* + * Accept an "ip:port" address as displayed in /proc/net/ * + * and convert it into a human readable form, like: + * "0500000A:0016" -> ("10.0.0.5", 22) + * "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)*/ +address *decode_address(char Addr[], int family) +{ + address * Address; + Address = (address *)calloc(1, sizeof(address)); + check_mem(Address); + char IP[50]; + sscanf(Addr,"%s:%x",IP,&(Address->port)); + if(family == AF_INET) + { + Address = decodeIPv4(IP, Address); + } + else + { + Address = decodeIPv6(IP, Address); + } + if(Address->port == 0) + { + strcpy(Address->ip,"NONE"); + Address->port = -1; + return Address; + } + return Address; + error: + if(Address) + { + free(Address); + } + return NULL; +} +/* return Inode pointer with required inode(int)*/ +Inodes *find_inode(Inodes **inodes,int inode) +{ + int index = hashfunction(inode); + Inodes *tmp=inodes[index]; + if(tmp) + { + while(tmp->inode != inode) + { + tmp = tmp->Next_collision; + if(tmp==NULL) + return NULL; + } + return tmp; + } + return NULL; +} +/* Parse /proc/net/tcp* and /proc/net/udp* files. */ +ConnInfo* process_inet(char filepath[], int family, int type_,Inodes** inodes,pid_t filter_pid) +{ + FILE *fp = NULL; + ConnInfo *ret = NULL; + //Conn *ret=NULL; + Inodes *inodeptr; + char line[LINE_MAX]; + char *tmp,*laddr,*raddr; + int i = 0, inode, fd, status; + pid_t pid; + ret = (ConnInfo*)calloc(1,sizeof(ConnInfo)); + check_mem(ret); + ret->nitems=0; + ret->Connections = (Conn*)calloc(1, sizeof(Conn)); + check_mem(ret->Connections); + if (filepath[strlen(filepath)-1] == '6' && (access(filepath, F_OK )==-1)) + {//doesnot support IPv6 + ret->Connections=NULL; + return ret; + } + fp = fopen(filepath, "r"); + check(fp, "Couldn't open %s",filepath); + + check(fgets(line,LINE_MAX,fp)," ");/* skip first line */ + while (fgets(line,LINE_MAX,fp)) + { + //tmpptr = (Conn*)calloc(1, sizeof(Conn)); + //check_mem(tmpptr); + tmp = strtok(line, " "); /* sl */ + tmp = strtok(NULL, " "); /* local_address*/ + laddr = tmp; + tmp = strtok(NULL, " "); /* remaddress*/ + raddr = tmp; + tmp = strtok(NULL, " "); /* status*/ + status = strtol(tmp,NULL,16); + for(i = 0;i< 5;i++) + { + tmp = strtok(NULL, " "); /* not required parts in file*/ + } + tmp = strtok(NULL, " "); /* uid*/ + inode = atoi(tmp); + inodeptr = find_inode(inodes,inode); + if(inodeptr) + { + fd = inodeptr->fd; + pid = inodeptr->pid; + } + else + { + fd = -1; + pid = -1; + } + ret->Connections[ret->nitems].fd = fd; + ret->Connections[ret->nitems].pid = pid; + ret->Connections[ret->nitems].family = family; + if ((filter_pid != -1) && (pid != filter_pid)) + { + continue; + } + else + { + if (type_ == SOCK_STREAM) + ret->Connections[ret->nitems].status = (status-1); + else + ret->Connections[ret->nitems].status = NONE; + ret->Connections[ret->nitems].type = type_; + ret->Connections[ret->nitems].laddr = decode_address(laddr, family); + ret->Connections[ret->nitems].raddr = decode_address(raddr, family); + + ret->nitems++; + if(ret->nitems > 0) + { + ret->Connections = (Conn*)realloc(ret->Connections,(ret->nitems+1)*(sizeof(Conn))); + check_mem(ret->Connections); + } + } + } + fclose(fp); + return ret; + error: + if(fp) + fclose(fp); + if(ret) + free_ConnInfo(ret); + return NULL; +} +/* Parse /proc/net/unix files.*/ +ConnInfo *process_unix(char filepath[], int family,Inodes** inodes,pid_t filter_pid) +{ + FILE *fp = NULL; + ConnInfo *ret=NULL; + Inodes *inode_same_pid=NULL,*inodeptr; + int fd[10],pid[10]; + char line[LINE_MAX]; + int i = 0, inode, type; + char *tmp,*path; + //log_info("\nprocess_unix started\n"); + fp = fopen(filepath, "r"); + check(fp, "Couldn't open %s",filepath); + ret = (ConnInfo*)calloc(1, sizeof(ConnInfo)); + check_mem(ret); + ret->Connections = (Conn*)calloc(1, sizeof(Conn)); + check_mem(ret->Connections); + ret->nitems = 0; + fgets(line,LINE_MAX,fp); + while (fgets(line,LINE_MAX,fp)) + { + path = NULL; + //log_info("\nfile read line\n"); + tmp = strtok(line, " ");/* sl No*/ + for(i = 0;i< 3;i++) + { + tmp = strtok(NULL, " "); /* not required parts in file*/ + } + tmp = strtok(NULL, " "); /* type */ + type = atoi(tmp); + tmp = strtok(NULL, " "); + tmp = strtok(NULL, " "); /* inode */ + inode = atoi(tmp); + path = strtok(NULL, " "); + inodeptr = find_inode(inodes,inode); + if(inodeptr) + { + //log_info("\n inode found matching \n"); + i=0; + inode_same_pid = inodeptr; + while(inode_same_pid) + { + fd[i]= inode_same_pid->fd; + pid[i]= inode_same_pid->pid; + i++; + inode_same_pid = inode_same_pid->Next_in_list; + } + fd[i]=-1; + pid[i]=-1; + } + else { + fd[0] = fd[1] = -1; + pid[0] = pid[1] = -1; + } + i=0; + do + { + ret->Connections[ret->nitems].fd = fd[i]; + ret->Connections[ret->nitems].pid = pid[i]; + i++; + ret->Connections[ret->nitems].family = family; + ret->Connections[ret->nitems].type = type; + if ((filter_pid != -1) && (ret->Connections[ret->nitems].pid != filter_pid)) + { + continue; + } + else + { + ret->Connections[ret->nitems].status = NONE; + ret->Connections[ret->nitems].laddr = (address *)calloc(1,sizeof(address)); + check_mem(ret->Connections[ret->nitems].laddr); + ret->Connections[ret->nitems].laddr->port = -1; + ret->Connections[ret->nitems].raddr = (address *)calloc(1,sizeof(address)); + check_mem(ret->Connections[ret->nitems].raddr); + ret->Connections[ret->nitems].raddr->port = -1; + if(path != NULL) + sscanf(path,"%s\n",ret->Connections[ret->nitems].laddr->ip);//path + else + strcpy(ret->Connections[ret->nitems].laddr->ip, "");//path + strcpy(ret->Connections[ret->nitems].raddr->ip, ""); + ret->nitems++; + if(ret->nitems > 0) + { + ret->Connections = (Conn*)realloc(ret->Connections,(ret->nitems+1)*(sizeof(Conn))); + check_mem(ret->Connections); + } + } + }while(fd[i]!=-1); + } + fclose(fp); + return ret; + error: + if(fp) + fclose(fp); + if(ret) + free_ConnInfo(ret); + return NULL; +} + +ConnInfo *retrive(char kind[],pid_t pid) +{ + uint32_t i=0,j=0,k=0,l=0; + bool duplicate = false; + Inodes **inodes = NULL; + ConnInfo *ret=NULL; + ConnInfo *ls; + char tmp[20]; + + while(strcmp(tmap.kind_label[i],kind)) + { + check(tmap.kind_label[i]!='\0',"invalid %s kind argument",kind); + i++; + } + if(pid!=-1) + { + inodes = (Inodes**)calloc(1,sizeof(Inodes *)); + check_mem(inodes); + inodes[0] = get_proc_inodes(pid); + if (inodes[0]) + return NULL; + } + else + { + inodes = get_all_inodes(); + } + check_mem(inodes); + ret = (ConnInfo*)calloc(1,sizeof(ConnInfo)); + check_mem(ret); + ret->Connections = (Conn*)calloc(1,sizeof(Conn)); + check_mem(ret->Connections); + ret->nitems=0; + while (tmap.kind[i][j]!=NULL) + { + if ((tmap.kind[i][j]->family == AF_INET) || (tmap.kind[i][j]->family == AF_INET6)) + { + snprintf(tmp, sizeof(tmp), "/proc/net/%s",tmap.kind[i][j]->name); + ls = process_inet(tmp,tmap.kind[i][j]->family,tmap.kind[i][j]->type_,inodes,pid); + check_mem(ls); + } + else + { + snprintf(tmp, sizeof(tmp), "/proc/net/%s",tmap.kind[i][j]->name); + ls = process_unix(tmp,tmap.kind[i][j]->family,inodes,pid); + check_mem(ls) + } + k=0; + while(k < ls->nitems/*ls->Connections[k] != NULL*/) + { + duplicate = false;//for finding duplicate + for(l=0;lnitems;l++) + { + if(IsSame(&(ret->Connections[l]),&(ls->Connections[k]))) + { + duplicate = true; + break; + } + } + if(!duplicate) + { + ret->Connections[ret->nitems].family = ls->Connections[k].family; + ret->Connections[ret->nitems].fd = ls->Connections[k].fd; + ret->Connections[ret->nitems].laddr = ls->Connections[k].laddr; + ret->Connections[ret->nitems].pid = ls->Connections[k].pid; + ret->Connections[ret->nitems].raddr = ls->Connections[k].raddr; + ret->Connections[ret->nitems].status = ls->Connections[k].status; + ret->Connections[ret->nitems].type = ls->Connections[k].type; + ret->nitems++; + } + k++; + if(ret->nitems > 0) + { + ret->Connections = (Conn*)realloc(ret->Connections,((ret->nitems + 1)*sizeof(Conn))); + check_mem(ret->Connections); + } + } + free(ls); + j++; + } + return ret; + error: + if(inodes) + free(inodes); + if(ret) + free_ConnInfo(ret); + return NULL; +} +ConnInfo *net_connections(char kind[]) +{ + return retrive(kind,-1); +} +void free_ConnInfo(ConnInfo *c) +{ + uint32_t i; + for(i=0;i < c->nitems;i++) + { + free(c->Connections[i].laddr); + free(c->Connections[i].raddr); + } + free(c); +} /* The following function is an ugly workaround to ensure that coverage From caa781278ffdfba0d16614224f164cb16c47fc94 Mon Sep 17 00:00:00 2001 From: libin-n-g Date: Thu, 22 Jun 2017 12:16:24 +0530 Subject: [PATCH 2/7] Add tests for net_connections --- tests/test_net.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/test_net.py b/tests/test_net.py index 35b746a..3d9d11b 100644 --- a/tests/test_net.py +++ b/tests/test_net.py @@ -25,3 +25,49 @@ def test_net_io_counters(flush): assert psutil_counters[name].errout == errout assert psutil_counters[name].dropin == dropin assert psutil_counters[name].dropout == dropout + +def test_number_of_connections(flush): + kind = ["all", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "unix", "inet", "inet4", "inet6"] + for each in kind: + expected_connections = psutil.net_connections(each) + actual_connections = P.net_connections(each) + assert actual_connections.nitems == len(expected_connections) + + +def test_all_net_connection_attribs(flush): + kind = ["all", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "unix", "inet", "inet4", "inet6"] + con_status = ffi.typeof('enum con_status') + for each in kind: + expected_connections = psutil.net_connections(each) + actual_connections = P.net_connections(each) + for i in range(actual_connections.nitems): + fd = actual_connections.Connections[i].fd + family = actual_connections.Connections[i].family + _type = actual_connections.Connections[i].type + if ffi.string(actual_connections.Connections[i].laddr.ip) == 'NONE': + laddr = () + elif actual_connections.Connections[i].laddr.port == -1: + laddr = ffi.string(actual_connections.Connections[i].laddr.ip) + else: + laddr = ffi.string(actual_connections.Connections[i].laddr.ip), actual_connections.Connections[i].laddr.port + if ffi.string(actual_connections.Connections[i].raddr.ip) == 'NONE': + raddr = () + elif actual_connections.Connections[i].raddr.port == -1: + raddr = ffi.string(actual_connections.Connections[i].raddr.ip) + else: + raddr = ffi.string(actual_connections.Connections[i].raddr.ip), actual_connections.Connections[i].raddr.port + status = con_status.elements[actual_connections.Connections[i].status] + pid = actual_connections.Connections[i].pid + found = False + for part in expected_connections: + if all([part.fd == fd, + part.family == family, + part.type == _type, + part.laddr == laddr, + part.raddr == raddr, + part.status == status, + part.pid == pid or (part.pid is None and pid == -1)]): + found = True + break + assert found, """No match for conn (fd = '{}', family= '{}', type= '{}', laddr = '{}', raddr = '{}', status = '{}', pid = '{}')""".format(fd, family, _type, laddr, raddr, status, pid) + From 4c4dcbffcb25a8f8873836ec522a32d324c017d2 Mon Sep 17 00:00:00 2001 From: AthuL Date: Thu, 29 Jun 2017 17:07:22 +0530 Subject: [PATCH 3/7] Add net_if_stats API --- bindings/python/pycpslib_build.py | 6 +- driver.c | 17 +++ pslib.h | 25 ++++ pslib_linux.c | 207 +++++++++++++++++++++++++++++- tests/test_net.py | 1 - 5 files changed, 249 insertions(+), 7 deletions(-) diff --git a/bindings/python/pycpslib_build.py b/bindings/python/pycpslib_build.py index 768c06b..bbeee3b 100644 --- a/bindings/python/pycpslib_build.py +++ b/bindings/python/pycpslib_build.py @@ -18,10 +18,8 @@ library_dirs = [project_root], include_dirs = [project_root]) -ffi.cdef(''' -typedef int32_t pid_t; -typedef int32_t bool; -''') +ffi.cdef('''typedef int32_t pid_t; +typedef _Bool bool;''') lines = open(project_root+"/pslib.h").readlines() diff --git a/driver.c b/driver.c index 78aa6e7..fbe8f9b 100644 --- a/driver.c +++ b/driver.c @@ -18,6 +18,7 @@ void test_diskusage() { du.total, du.used, du.free, du.percent); } + void test_diskpartitioninfo() { uint32_t i; DiskPartitionInfo *phys_dp, *all_dp; @@ -444,6 +445,21 @@ void test_net_connections() free_ConnInfo(result); } } +void test_netifstats() +{ + NetIfStatsInfo *n; + NetIfStats *dp; + uint32_t i; + n = net_if_stats(); + dp = n->ifstats; + printf(" -- net_if_stats (interface count: %" PRIu32 ")\n", n->nitems); + for (i = 0; i < n->nitems; i++) { + printf("%s\t:snicstats(isup=%s, duplex=%" PRIu32", speed=%" PRIu32", mtu=%" PRIu32")\n",dp->name,dp->isup?"true":"false",dp->duplex,dp->speed,dp->mtu); + dp++; + } + free_net_ifstats_info(n); + printf("\n"); +} int main(void) { test_diskusage(); @@ -468,4 +484,5 @@ int main(void) { test_pid_exists(); test_process(); test_net_connections(); + test_netifstats(); } diff --git a/pslib.h b/pslib.h index c932221..4e08ee4 100644 --- a/pslib.h +++ b/pslib.h @@ -74,6 +74,26 @@ enum proc_priority { REALTIME_PRIORITY_CLASS }; +typedef struct { + uint32_t duplex; + uint32_t speed; +}DuplexSpeed; + +typedef struct { + char *name; + bool isup; + uint32_t duplex; + uint32_t speed; + uint32_t mtu; +}NetIfStats; + + +typedef struct { + uint32_t nitems; + NetIfStats *ifstats; +}NetIfStatsInfo; + + typedef struct { uint64_t total; uint64_t used; @@ -267,6 +287,11 @@ void free_ConnInfo(ConnInfo *); /* Required to avoid [-Wimplicit-function-declaration] for python bindings */ void gcov_flush(void); +NetIfStatsInfo *net_if_stats(void); +uint32_t net_if_mtu(char *); +DuplexSpeed * net_if_duplex_speed(char*); +uint32_t net_if_flags(char *); +void free_net_ifstats_info(NetIfStatsInfo *) ; // disk_io_counters_per_disk // net_io_counters_per_nic diff --git a/pslib_linux.c b/pslib_linux.c index 22937de..6ff5d08 100644 --- a/pslib_linux.c +++ b/pslib_linux.c @@ -19,8 +19,18 @@ #include "pslib.h" #include "common.h" - #define HASHSIZE 2731 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include void __gcov_flush(void); @@ -42,6 +52,7 @@ static int clean_cmdline(char *ip, int len) } ip[--i] = '\0'; return replacements; + } /* Internal functions */ @@ -127,7 +138,7 @@ static int physical_cpu_count() { check_mem(line); while (fgets(line, 90, fp) != NULL) { - if (strncasecmp(line, "physical id", 11) == 0) { + if (strncaseecmp(line, "physical id", 11) == 0) { strtok(line, ":"); id = strtol(strtok(NULL, " "), NULL, 10); /* TODO: Assuming that physical id is a number */ @@ -707,6 +718,8 @@ NetIOCounterInfo *net_io_counters() { tmp = strtok(NULL, " \n"); /* Drops out 10*/ nc->dropout = strtoul(tmp, NULL, 10); + + nc++; } fclose(fp); @@ -1698,6 +1711,194 @@ void free_ConnInfo(ConnInfo *c) free(c); } + +NetIfStatsInfo *net_if_stats() +{ + uint32_t n_stats = 15; + NetIOCounterInfo *counterinfo = net_io_counters(); + uint32_t num = counterinfo->nitems; + NetIOCounters *io_counters = counterinfo->iocounters; + uint32_t i=0; + + NetIfStatsInfo *ret = (NetIfStatsInfo * )calloc(1,sizeof(NetIfStatsInfo)); + NetIfStats *ifstats = (NetIfStats *)calloc(n_stats,sizeof(NetIfStats)); + NetIfStats *st = ifstats; + + check_mem(ifstats); + check_mem(ret); + + ret->nitems = 0; + ret->ifstats = ifstats; + + + + for(i=0;iisup = isup; + DuplexSpeed *tmp = net_if_duplex_speed(name); + st->name = (char*)malloc(sizeof(name)); + strcpy(st->name,name); + if(tmp->duplex == DUPLEX_FULL) + tmp->duplex=2; + else if(tmp->duplex == DUPLEX_HALF) + tmp->duplex=1; + else if(tmp->duplex == DUPLEX_UNKNOWN) + tmp->duplex=0; + st->duplex = tmp->duplex; + st->speed = tmp->speed; + free(tmp); + st->mtu = mtu; + st++; + ret->nitems++; + + if (ret->nitems == n_stats) + { + n_stats *= 2; + ifstats = (NetIfStats *)realloc(ifstats, sizeof(NetIfStats) * n_stats); + check_mem(ifstats); + ret->ifstats = ifstats; + st = ret->ifstats + ret->nitems; /* Move the cursor to the correct + value in case the realloc moved + the memory */ + } + + } + free_net_iocounter_info(counterinfo); + return ret; +error: + + free_net_iocounter_info(counterinfo); + free_net_ifstats_info(ret); + return NULL; + +} +void free_net_ifstats_info(NetIfStatsInfo *d) { + for (uint32_t i = 0; i < d->nitems; i++) { + free(d->ifstats[i].name); + } + free(d->ifstats); + free(d); +} +uint32_t net_if_mtu(char *name) { + char *nic_name = name; + int sock = 0; + int ret; + struct ifreq ifr; + + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == -1) + goto error; + + + strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); + ret = ioctl(sock, SIOCGIFMTU, &ifr); + + if (ret == -1) + goto error; + close(sock); + + + return ifr.ifr_mtu; +error: + if (sock != 0) + close(sock); + return -1; +} + +uint32_t net_if_flags(char *name) { + char *nic_name = name; + int sock = 0; + int ret; + struct ifreq ifr; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == -1) + goto error; + + strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); + + ret = ioctl(sock, SIOCGIFFLAGS, &ifr); + if (ret == -1) + goto error; + + close(sock); + if ((ifr.ifr_flags & IFF_UP) != 0) + return 1; + else + return 0; + +error: + if (sock != 0) + close(sock); + return -1; +} + +DuplexSpeed *net_if_duplex_speed(char *name) { + char *nic_name = name; + int sock = 0; + int ret; + int duplex; + int speed; + + + + struct ifreq ifr; + struct ethtool_cmd ethcmd; + if(nic_name == NULL) + return NULL; + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == -1) + goto error; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + // duplex and speed + memset(ðcmd, 0, sizeof ethcmd); + ethcmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = (void *)ðcmd; + ret = ioctl(sock, SIOCETHTOOL, &ifr); + + if (ret != -1) { + duplex = ethcmd.duplex; + speed = ethcmd.speed; + } + + else { + if ((errno == EOPNOTSUPP) || (errno == EINVAL)) { + // EOPNOTSUPP may occur in case of wi-fi cards. + // For EINVAL see: + // https://github.com/giampaolo/psutil/issues/797 + // #issuecomment-202999532 + duplex = DUPLEX_UNKNOWN; + speed = 0; + } + else { + goto error; + } + } + + close(sock); + + DuplexSpeed *retv = (DuplexSpeed*)malloc(sizeof(DuplexSpeed)); + check_mem(retv); + + retv->duplex=duplex; + retv->speed=speed; + + return retv; + +error: + if (sock != -1) + close(sock); + return NULL; +} + + + /* The following function is an ugly workaround to ensure that coverage data can be manually flushed to disk during py.test invocations. If @@ -1706,3 +1907,5 @@ void free_ConnInfo(ConnInfo *c) */ void gcov_flush(void) { __gcov_flush(); } + + diff --git a/tests/test_net.py b/tests/test_net.py index 3d9d11b..da7d350 100644 --- a/tests/test_net.py +++ b/tests/test_net.py @@ -70,4 +70,3 @@ def test_all_net_connection_attribs(flush): found = True break assert found, """No match for conn (fd = '{}', family= '{}', type= '{}', laddr = '{}', raddr = '{}', status = '{}', pid = '{}')""".format(fd, family, _type, laddr, raddr, status, pid) - From 65412c357da031cd2f5eab192f6de1135f230043 Mon Sep 17 00:00:00 2001 From: AthuL Date: Thu, 29 Jun 2017 17:14:31 +0530 Subject: [PATCH 4/7] Add test for net_if_stats --- pslib_linux.c | 2 +- tests/test_net.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pslib_linux.c b/pslib_linux.c index 6ff5d08..97d82a4 100644 --- a/pslib_linux.c +++ b/pslib_linux.c @@ -138,7 +138,7 @@ static int physical_cpu_count() { check_mem(line); while (fgets(line, 90, fp) != NULL) { - if (strncaseecmp(line, "physical id", 11) == 0) { + if (strncasecmp(line, "physical id", 11) == 0) { strtok(line, ":"); id = strtol(strtok(NULL, " "), NULL, 10); /* TODO: Assuming that physical id is a number */ diff --git a/tests/test_net.py b/tests/test_net.py index da7d350..155f0e5 100644 --- a/tests/test_net.py +++ b/tests/test_net.py @@ -70,3 +70,23 @@ def test_all_net_connection_attribs(flush): found = True break assert found, """No match for conn (fd = '{}', family= '{}', type= '{}', laddr = '{}', raddr = '{}', status = '{}', pid = '{}')""".format(fd, family, _type, laddr, raddr, status, pid) + +def test_net_if_stats(flush): + + psutil_stats = psutil.net_if_stats() + pslib_stats = P.net_if_stats() + + + for i in range(pslib_stats.nitems): + name = ffi.string(pslib_stats.ifstats[i].name) + isup = pslib_stats.ifstats[i].isup + duplex = pslib_stats.ifstats[i].duplex + speed = pslib_stats.ifstats[i].speed + mtu = pslib_stats.ifstats[i].mtu + + + assert isup==psutil_stats[name].isup + assert duplex==psutil_stats[name].duplex + assert speed==psutil_stats[name].speed + assert mtu==psutil_stats[name].mtu + From 4613262aacc23dbf263fed6d300d320b6652881f Mon Sep 17 00:00:00 2001 From: libin-n-g Date: Thu, 29 Jun 2017 20:22:40 +0530 Subject: [PATCH 5/7] Fixes #1 --- tests/test_net.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_net.py b/tests/test_net.py index 155f0e5..8a61f29 100644 --- a/tests/test_net.py +++ b/tests/test_net.py @@ -64,7 +64,7 @@ def test_all_net_connection_attribs(flush): part.family == family, part.type == _type, part.laddr == laddr, - part.raddr == raddr, + part.raddr == raddr or (part.raddr == None and raddr == ''), part.status == status, part.pid == pid or (part.pid is None and pid == -1)]): found = True From 7ac9e730f6be85ab37019e8bf4624be643937537 Mon Sep 17 00:00:00 2001 From: libin-n-g Date: Fri, 30 Jun 2017 12:40:50 +0530 Subject: [PATCH 6/7] cleaning up and add comments --- driver.c | 31 +++++++++----------------- pslib_linux.c | 60 ++++++++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/driver.c b/driver.c index fbe8f9b..01bb985 100644 --- a/driver.c +++ b/driver.c @@ -393,56 +393,45 @@ void test_net_connections() printf("\nnet_connections\n"); ConnInfo *result; char *array[] ={"all", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "unix", "inet", "inet4", "inet6"}; - int i=0,j=0; + uint32_t i=0,j=0; for(j=0;j < 11;j++) { i=0; - result = net_connections(array[j]); printf("\n%s\n",array[j]); if(result) { - while(i < (int)result->nitems) + while(i < result->nitems) { - printf("fd=%d, family=%d, type=%d,",result->Connections[i].fd,result->Connections[i].family,result->Connections[i].type); + printf("sconn(fd=%d, family=%d, type=%d,",result->Connections[i].fd,result->Connections[i].family,result->Connections[i].type); if(!(strcmp(result->Connections[i].laddr->ip, "NONE"))) - { printf(" laddr=(),"); - } else if((result->Connections[i].laddr->port == -1)) - { printf(" laddr='%s',",result->Connections[i].laddr->ip); - } else - { printf(" laddr=('%s', %d),",result->Connections[i].laddr->ip,result->Connections[i].laddr->port); - } if(!(strcmp(result->Connections[i].raddr->ip, "NONE"))) - { printf(" raddr=(),"); - } else if(result->Connections[i].laddr->port == -1) { - printf(" raddr='%s',",result->Connections[i].raddr->ip); + if(!strcmp(result->Connections[i].raddr->ip,"")) + printf(" raddr=None,"); + else + printf(" raddr='%s',",result->Connections[i].raddr->ip); } else - { printf(" raddr=('%s', %d),",result->Connections[i].raddr->ip,result->Connections[i].raddr->port); - } printf(" status='%s',", status[result->Connections[i].status]); if(result->Connections[i].pid==-1) - { - printf(" pid=None\n"); - } + printf(" pid=None)\n"); else - { - printf(" pid=%d\n", result->Connections[i].pid); - } + printf(" pid=%d)\n", result->Connections[i].pid); i++; } } free_ConnInfo(result); + printf("\n"); } } void test_netifstats() diff --git a/pslib_linux.c b/pslib_linux.c index 97d82a4..2fce15a 100644 --- a/pslib_linux.c +++ b/pslib_linux.c @@ -15,23 +15,23 @@ #include #include #include - - -#include "pslib.h" -#include "common.h" -#define HASHSIZE 2731 #include #include #include #include #include -#include #include #include #include #include #include + +#include "pslib.h" +#include "common.h" +#define HASHSIZE 2731 + + void __gcov_flush(void); static int clean_cmdline(char *ip, int len) @@ -1182,6 +1182,15 @@ int isnumber(char c[]) } return 1; } +void free_Pidlist(Pidlist *p) +{ + if(p) + { + if(p->pid) + free(p->pid); + free(p); + } +} // Returns list of all PIDs Pidlist *pids() { @@ -1208,20 +1217,13 @@ Pidlist *pids() return ret; error: if(ret) - { - if(ret->pid) - { - free(ret->pid); - } - free(ret); - } + free_Pidlist(ret); if(d) - { closedir(d); - } return NULL; } + Inodes *get_proc_inodes(pid_t pid) { DIR *d; @@ -1319,7 +1321,7 @@ Inodes *Update(Inodes *ls_element, Inodes *inodes) Inodes **get_all_inodes() { Inodes **inodes = NULL, *ls=NULL; - Pidlist *PID; + Pidlist *PID = NULL; int i,j=0,index=0; inodes = (Inodes **)calloc(HASHSIZE, sizeof(Inodes*)); check_mem(inodes); @@ -1333,8 +1335,11 @@ Inodes **get_all_inodes() inodes[index]=Update(&ls[j],inodes[index]); } } + free_Pidlist(PID); return inodes; error: + if(PID) + free_Pidlist(PID); return NULL; } /* convert IPv6 address to human readable form like @@ -1428,7 +1433,6 @@ ConnInfo* process_inet(char filepath[], int family, int type_,Inodes** inodes,pi { FILE *fp = NULL; ConnInfo *ret = NULL; - //Conn *ret=NULL; Inodes *inodeptr; char line[LINE_MAX]; char *tmp,*laddr,*raddr; @@ -1446,7 +1450,6 @@ ConnInfo* process_inet(char filepath[], int family, int type_,Inodes** inodes,pi } fp = fopen(filepath, "r"); check(fp, "Couldn't open %s",filepath); - check(fgets(line,LINE_MAX,fp)," ");/* skip first line */ while (fgets(line,LINE_MAX,fp)) { @@ -1485,13 +1488,17 @@ ConnInfo* process_inet(char filepath[], int family, int type_,Inodes** inodes,pi } else { + ret->Connections[ret->nitems].laddr = NULL; + ret->Connections[ret->nitems].raddr = NULL; if (type_ == SOCK_STREAM) ret->Connections[ret->nitems].status = (status-1); else ret->Connections[ret->nitems].status = NONE; ret->Connections[ret->nitems].type = type_; ret->Connections[ret->nitems].laddr = decode_address(laddr, family); + check(ret->Connections[ret->nitems].laddr,"decode Address failed"); ret->Connections[ret->nitems].raddr = decode_address(raddr, family); + check(ret->Connections[ret->nitems].raddr,"decode Address failed"); ret->nitems++; if(ret->nitems > 0) @@ -1632,9 +1639,7 @@ ConnInfo *retrive(char kind[],pid_t pid) return NULL; } else - { inodes = get_all_inodes(); - } check_mem(inodes); ret = (ConnInfo*)calloc(1,sizeof(ConnInfo)); check_mem(ret); @@ -1656,6 +1661,8 @@ ConnInfo *retrive(char kind[],pid_t pid) check_mem(ls) } k=0; + /* NOTE : psutil 2.1.2 does not remove duplicate therefore test_number_of_connections may fail + Reason : psutil 5.2.2 uses set but psutil 2.1.2 uses list */ while(k < ls->nitems/*ls->Connections[k] != NULL*/) { duplicate = false;//for finding duplicate @@ -1705,13 +1712,15 @@ void free_ConnInfo(ConnInfo *c) uint32_t i; for(i=0;i < c->nitems;i++) { - free(c->Connections[i].laddr); - free(c->Connections[i].raddr); + if(c->Connections[i].laddr) + free(c->Connections[i].laddr); + if(c->Connections[i].raddr) + free(c->Connections[i].raddr); } free(c); } - +//NOT AVAILABLE ON PSUTIL 2.1.2 NetIfStatsInfo *net_if_stats() { uint32_t n_stats = 15; @@ -1729,13 +1738,9 @@ NetIfStatsInfo *net_if_stats() ret->nitems = 0; ret->ifstats = ifstats; - - - for(i=0;initems; i++) { free(d->ifstats[i].name); From 72e46d744d00277d127d2d55a43fa9c15c38eef2 Mon Sep 17 00:00:00 2001 From: libin-n-g Date: Tue, 1 Aug 2017 22:48:16 +0530 Subject: [PATCH 7/7] Resolving issues #3 due to conflicts in header files --- pslib_linux.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/pslib_linux.c b/pslib_linux.c index 2fce15a..f9821f8 100644 --- a/pslib_linux.c +++ b/pslib_linux.c @@ -4,29 +4,20 @@ #include #include #include -#include #include -#include -#include -#include -#include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include - #include "pslib.h" #include "common.h" #define HASHSIZE 2731