diff options
Diffstat (limited to 'toys/pending/netstat.c')
-rw-r--r-- | toys/pending/netstat.c | 219 |
1 files changed, 131 insertions, 88 deletions
diff --git a/toys/pending/netstat.c b/toys/pending/netstat.c index 3ee4c5a2..d6acd7a3 100644 --- a/toys/pending/netstat.c +++ b/toys/pending/netstat.c @@ -52,7 +52,7 @@ typedef union _iaddr6 { unsigned char b[16]; } iaddr6; -#define ADDR_LEN (INET6_ADDRSTRLEN + 1 + 5 + 1) //IPv6 addr len + : + port + '\0' +#define ADDR_LEN (INET6_ADDRSTRLEN + 1 + 5 + 1)//IPv6 addr len + : + port + '\0' //For unix states enum { @@ -68,21 +68,14 @@ typedef struct _pidlist { long inode; char name[21]; } PID_LIST; -PID_LIST *pid_list = NULL; -/* - * locate character in string. - */ -static char *strchr_nul(char *s, int c) -{ - while(*s != '\0' && *s != c) s++; - return (char*)s; -} +PID_LIST *pid_list = NULL; /* - * used to converts string into int and validate the input str for invalid int value or out-of-range. + * used to convert string into int and + * validate the input str for invalid int value or out-of-range. */ -static unsigned get_strtou(char *str, char **endp, int base) +static unsigned long get_strtou(char *str, char **endp, int base) { unsigned long uli; char *endptr; @@ -108,16 +101,20 @@ static unsigned get_strtou(char *str, char **endp, int base) } return uli; } + /* * used to retrive pid name from pid list. */ static const char *get_pid_name(unsigned long inode) { PID_LIST *tmp; + for (tmp = pid_list; tmp; tmp = tmp->next) if (tmp->inode == inode) return tmp->name; + return "-"; } + /* * For TCP/UDP/RAW display data. */ @@ -126,8 +123,9 @@ static void display_data(unsigned rport, char *label, unsigned state, unsigned uid, unsigned long inode) { char *ss_state = "UNKNOWN", buf[12]; - char *state_label[] = {"", "ESTABLISHED", "SYN_SENT", "SYN_RECV", "FIN_WAIT1", "FIN_WAIT2", - "TIME_WAIT", "CLOSE", "CLOSE_WAIT", "LAST_ACK", "LISTEN", "CLOSING", "UNKNOWN"}; + char *state_label[] = {"", "ESTABLISHED", "SYN_SENT", "SYN_RECV", "FIN_WAIT1", + "FIN_WAIT2", "TIME_WAIT", "CLOSE", "CLOSE_WAIT", + "LAST_ACK", "LISTEN", "CLOSING", "UNKNOWN"}; char user[11]; struct passwd *pw; @@ -147,12 +145,14 @@ static void display_data(unsigned rport, char *label, } else snprintf(user, sizeof(user), "%d", uid); xprintf("%3s %6d %6d ", label, rxq, txq); - xprintf((toys.optflags & FLAG_W) ? "%-51.51s %-51.51s " : "%-23.23s %-23.23s ", lip, rip); + xprintf((toys.optflags & FLAG_W) ? "%-51.51s %-51.51s " : "%-23.23s %-23.23s " + , lip, rip); xprintf("%-11s ", ss_state); - if ((toys.optflags & FLAG_e)) xprintf("%-10s %-11d ", user, inode); + if ((toys.optflags & FLAG_e)) xprintf("%-10s %-11ld ", user, inode); if ((toys.optflags & FLAG_p)) xprintf("%s", get_pid_name(inode)); xputc('\n'); } + /* * For TCP/UDP/RAW show data. */ @@ -161,11 +161,15 @@ static void show_data(unsigned rport, char *label, unsigned rxq, unsigned txq, unsigned long inode) { if (toys.optflags & FLAG_l) { - if (!rport && (state & 0xA)) display_data(rport, label, rxq, txq, lip, rip, state, uid, inode); - } else if (toys.optflags & FLAG_a) display_data(rport, label, rxq, txq, lip, rip, state, uid, inode); + if (!rport && (state & 0xA)) + display_data(rport, label, rxq, txq, lip, rip, state, uid, inode); + } else if (toys.optflags & FLAG_a) + display_data(rport, label, rxq, txq, lip, rip, state, uid, inode); //rport && (TCP | UDP | RAW) - else if (rport & (0x10 | 0x20 | 0x40)) display_data(rport, label, rxq, txq, lip, rip, state, uid, inode); + else if (rport & (0x10 | 0x20 | 0x40)) + display_data(rport, label, rxq, txq, lip, rip, state, uid, inode); } + /* * used to get service name. */ @@ -177,6 +181,7 @@ static char *get_servname(int port, char *label) if (ser) return xmprintf("%s", ser->s_name); return xmprintf("%u", (unsigned)ntohs(lport)); } + /* * used to convert address into text format. */ @@ -210,7 +215,8 @@ static void addr2str(int af, void *addr, unsigned port, char *buf, char *label) else sock_len = sizeof(struct sockaddr_in6); for (rp = result; rp; rp = rp->ai_next) - if (!getnameinfo(rp->ai_addr, sock_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICSERV)) + if (!getnameinfo(rp->ai_addr, sock_len, hbuf, sizeof(hbuf), sbuf, + sizeof(sbuf), NI_NUMERICSERV)) break; freeaddrinfo(result); @@ -228,17 +234,20 @@ static void addr2str(int af, void *addr, unsigned port, char *buf, char *label) else snprintf(ip+iplen, ADDR_LEN-iplen, ":%d", port); memcpy(buf, ip, ADDR_LEN); } + /* * display ipv4 info for TCP/UDP/RAW. */ static void show_ipv4(char *fname, char *label) { - FILE *fp = fopen((char *)fname, "r"); + FILE *fp = fopen(fname, "r"); if (!fp) { perror_msg("'%s'", fname); return; } - fgets(toybuf, sizeof(toybuf), fp); //skip header. + + if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. + while (fgets(toybuf, sizeof(toybuf), fp)) { char lip[ADDR_LEN] = {0,}, rip[ADDR_LEN] = {0,}; iaddr laddr, raddr; @@ -246,7 +255,8 @@ static void show_ipv4(char *fname, char *label) unsigned long inode; int nitems = sscanf(toybuf, " %d: %x:%x %x:%x %x %x:%x %*X:%*X %*X %d %*d %ld", - &num, &laddr.u, &lport, &raddr.u, &rport, &state, &txq, &rxq, &uid, &inode); + &num, &laddr.u, &lport, &raddr.u, &rport, &state, &txq, + &rxq, &uid, &inode); if (nitems == 10) { addr2str(AF_INET, &laddr, lport, lip, label); addr2str(AF_INET, &raddr, rport, rip, label); @@ -255,25 +265,31 @@ static void show_ipv4(char *fname, char *label) }//End of While fclose(fp); } + /* * display ipv6 info for TCP/UDP/RAW. */ static void show_ipv6(char *fname, char *label) { - FILE *fp = fopen((char *)fname, "r"); + FILE *fp = fopen(fname, "r"); if (!fp) { perror_msg("'%s'", fname); return; } - fgets(toybuf, sizeof(toybuf), fp); //skip header. + + if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. + while (fgets(toybuf, sizeof(toybuf), fp)) { char lip[ADDR_LEN] = {0,}, rip[ADDR_LEN] = {0,}; iaddr6 laddr6, raddr6; unsigned lport, rport, state, txq, rxq, num, uid; unsigned long inode; - int nitems = sscanf(toybuf, " %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x %*X:%*X %*X %d %*d %ld", - &num, &laddr6.u.a, &laddr6.u.b, &laddr6.u.c, &laddr6.u.d, &lport, &raddr6.u.a, &raddr6.u.b, - &raddr6.u.c, &raddr6.u.d, &rport, &state, &txq, &rxq, &uid, &inode); + int nitems = sscanf(toybuf, " %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x " + "%*X:%*X %*X %d %*d %ld", + &num, &laddr6.u.a, &laddr6.u.b, &laddr6.u.c, + &laddr6.u.d, &lport, &raddr6.u.a, &raddr6.u.b, + &raddr6.u.c, &raddr6.u.d, &rport, &state, &txq, &rxq, + &uid, &inode); if (nitems == 16) { addr2str(AF_INET6, &laddr6, lport, lip, label); addr2str(AF_INET6, &raddr6, rport, rip, label); @@ -282,6 +298,7 @@ static void show_ipv6(char *fname, char *label) }//End of While fclose(fp); } + /* * display unix socket info. */ @@ -292,30 +309,39 @@ static void show_unix_sockets(char *fname, char *label) perror_msg("'%s'", fname); return; } - fgets(toybuf, sizeof(toybuf), fp); //skip header. + + if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. + while (fgets(toybuf, sizeof(toybuf), fp)) { - unsigned long int refcount, label, flags, inode; + unsigned long refcount, label, flags, inode; int nitems = 0, path_offset = 0, type, state; - char sock_flags[32] = {0,}, *sock_type, *sock_state, *bptr = toybuf; + char sock_flags[32] = {0,}, *sock_type, *sock_state, *bptr = toybuf, *term; if (!toybuf[0]) continue; + nitems = sscanf(toybuf, "%*p: %lX %lX %lX %X %X %lu %n", &refcount, &label, &flags, &type, &state, &inode, &path_offset); + //for state one less if (nitems < 6) break; + if (toys.optflags & FLAG_l) { - if ( !((state == SOCK_NOT_CONNECTED) && (flags & SOCK_ACCEPTCON)) ) continue; + if ( !((state == SOCK_NOT_CONNECTED) && (flags & SOCK_ACCEPTCON)) ) + continue; } else if (!(toys.optflags & FLAG_a)) { if ((state == SOCK_NOT_CONNECTED) && (flags & SOCK_ACCEPTCON)) continue; } //prepare socket type, state and flags. { - char *ss_type[] = { "", "STREAM", "DGRAM", "RAW", "RDM", "SEQPACKET", "UNKNOWN"}; - char *ss_state[] = { "FREE", "LISTENING", "CONNECTING", "CONNECTED", "DISCONNECTING", "UNKNOWN"}; + char *ss_type[] = { "", "STREAM", "DGRAM", "RAW", "RDM", "SEQPACKET", + "UNKNOWN"}; + char *ss_state[] = { "FREE", "LISTENING", "CONNECTING", "CONNECTED", + "DISCONNECTING", "UNKNOWN"}; int sz = ARRAY_LEN(ss_type);//sizeof(ss_type)/sizeof(ss_type[0]); - if ( (type < SOCK_STREAM) || (type > SOCK_SEQPACKET) ) sock_type = ss_type[sz-1]; + if ( (type < SOCK_STREAM) || (type > SOCK_SEQPACKET) ) + sock_type = ss_type[sz-1]; else sock_type = ss_type[type]; sz = ARRAY_LEN(ss_state);//sizeof(ss_state)/sizeof(ss_state[0]); @@ -331,15 +357,17 @@ static void show_unix_sockets(char *fname, char *label) if (flags & SOCK_NO_SPACE) strcat(sock_flags, "N "); strcat(sock_flags, "]"); } - xprintf("%-5s %-6ld %-11s %-10s %-13s %8lu ", (!label ? "unix" : "??"), refcount, sock_flags, sock_type, sock_state, inode); + xprintf("%-5s %-6ld %-11s %-10s %-13s %8lu ", (!label ? "unix" : "??"), + refcount, sock_flags, sock_type, sock_state, inode); if (toys.optflags & FLAG_p) xprintf("%-20s", get_pid_name(inode)); bptr += path_offset; - *strchr_nul(bptr, '\n') = '\0'; + if ((term = strchr(bptr, '\n'))) *term = '\0'; xprintf("%s\n", bptr); }//End of while fclose(fp); } + /* * extract inode value from the link. */ @@ -359,16 +387,19 @@ static long ss_inode(char *link) } return inode; } + /* * add inode and progname in the pid list. */ static void add2list(long inode) { PID_LIST *node = pid_list; + for(; node; node = node->next) { if(node->inode == inode) return; } + PID_LIST *new = (PID_LIST *)xzalloc(sizeof(PID_LIST)); new->inode = inode; xstrncpy(new->name, TT.current_name, sizeof(new->name)); @@ -423,6 +454,7 @@ static int scan_pids(struct dirtree *node) if (!node->parent) return DIRTREE_RECURSE; if ((pid = atol(node->name))) scan_pid(pid); + return 0; } @@ -438,12 +470,13 @@ static void clean_pid_list(void) pid_list = tmp; } } + /* * For TCP/UDP/RAW show the header. */ static void show_header(void) { - xprintf("\nProto Recv-Q Send-Q "); + xprintf("Proto Recv-Q Send-Q "); xprintf((toys.optflags & FLAG_W) ? "%-51s %-51s" : "%-23s %-23s", "Local Address", "Foreign Address"); xprintf(" State "); @@ -451,13 +484,14 @@ static void show_header(void) if (toys.optflags & FLAG_p) xprintf(" PID/Program Name"); xputc('\n'); } + /* * used to get the flag values for route command. */ -static void get_flag_value(char **flagstr, int flags) +static void get_flag_value(char *flagstr, int flags) { int i = 0; - char *str = *flagstr; + char *str = flagstr; static const char flagchars[] = "GHRDMDAC"; static const unsigned flagarray[] = { RTF_GATEWAY, @@ -470,10 +504,12 @@ static void get_flag_value(char **flagstr, int flags) RTF_CACHE }; *str++ = 'U'; + while ( (*str = flagchars[i]) ) { if (flags & flagarray[i++]) ++str; } } + /* * extract inet4 route info from /proc/net/route file and display it. */ @@ -483,85 +519,87 @@ static void display_routes(int is_more_info, int notresolve) unsigned long dest, gate, mask; int flags, ref, use, metric, mss, win, irtt; char iface[64]={0,}; - char *flag_val = xzalloc(10); //there are 9 flags "UGHRDMDAC" for route. + char flag_val[10]={0,}; //there are 9 flags "UGHRDMDAC" for route. FILE *fp = xfopen("/proc/net/route", "r"); + + if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. + xprintf("Kernel IP routing table\n" - "Destination Gateway Genmask Flags %s Iface\n", - is_more_info ? " MSS Window irtt" : "Metric Ref Use"); - fgets(toybuf, sizeof(toybuf), fp); //skip 1st line. + "Destination Gateway Genmask Flags %s Iface\n", + is_more_info ? " MSS Window irtt" : "Metric Ref Use"); + while (fgets(toybuf, sizeof(toybuf), fp)) { int nitems = 0; char *destip = NULL, *gateip = NULL, *maskip = NULL; - memset(flag_val, 0, 10); - nitems = sscanf(toybuf, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", - iface, &dest, &gate, &flags, &ref, &use, &metric, &mask, &mss, &win, &irtt); + nitems = sscanf(toybuf, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", iface, &dest, + &gate, &flags, &ref, &use, &metric, &mask, &mss, &win, &irtt); if (nitems != 11) {//EOF with no (nonspace) chars read. if ((nitems < 0) && feof(fp)) break; perror_exit("sscanf"); } + //skip down interfaces. if (!(flags & RTF_UP)) continue; if (dest) {//For Destination - if (inet_ntop(AF_INET, &dest, toybuf, sizeof(toybuf)) ) destip = xstrdup(toybuf); + if (inet_ntop(AF_INET, &dest, toybuf, sizeof(toybuf)) ) + destip = xstrdup(toybuf); } else { if (!notresolve) destip = xstrdup("default"); else destip = xstrdup("0.0.0.0"); } + if (gate) {//For Gateway - if (inet_ntop(AF_INET, &gate, toybuf, sizeof(toybuf)) ) gateip = xstrdup(toybuf); + if (inet_ntop(AF_INET, &gate, toybuf, sizeof(toybuf)) ) + gateip = xstrdup(toybuf); } else { if (!notresolve) gateip = xstrdup("*"); else gateip = xstrdup("0.0.0.0"); } + //For Mask - if (inet_ntop(AF_INET, &mask, toybuf, sizeof(toybuf)) ) maskip = xstrdup(toybuf); + if (inet_ntop(AF_INET, &mask, toybuf, sizeof(toybuf)) ) + maskip = xstrdup(toybuf); //Get flag Values - get_flag_value(&flag_val, (flags & IPV4_MASK)); + get_flag_value(flag_val, flags & IPV4_MASK); if (flags & RTF_REJECT) flag_val[0] = '!'; + xprintf("%-15.15s %-15.15s %-16s%-6s", destip, gateip, maskip, flag_val); + if (is_more_info) xprintf("%5d %-5d %6d %s\n", mss, win, irtt, iface); + else xprintf("%-6d %-2d %7d %s\n", metric, ref, use, iface); + if (destip) free(destip); if (gateip) free(gateip); if (maskip) free(maskip); - if (is_more_info) xprintf("%5d %-5d %6d %s\n", mss, win, irtt, iface); - else xprintf("%-6d %-2d %7d %s\n", metric, ref, use, iface); }//end of while. fclose(fp); - if (flag_val) free(flag_val); #undef IPV4_MASK - return; } + /* - * netstat utily main function. + * netstat utility main function. */ void netstat_main(void) { -#define IS_NETSTAT_PROTO_FLAGS_UP (toys.optflags & (FLAG_t | FLAG_u | FLAG_w | FLAG_x)) - int flag_listen_and_all = 0; +#define IS_NETSTAT_PROTO_FLAGS_UP (toys.optflags & (FLAG_t | FLAG_u | FLAG_w \ + | FLAG_x)) + + // For no parameter, add 't', 'u', 'w', 'x' options as default if (!toys.optflags) toys.optflags = FLAG_t | FLAG_u | FLAG_w | FLAG_x; - //When a is set - if (toys.optflags & FLAG_a) flag_listen_and_all = 1; - //when a and l both are set - if ( (toys.optflags & FLAG_a) && (toys.optflags & FLAG_l) ) - toys.optflags &= ~FLAG_l; - //when only a is set - if ( (toys.optflags & FLAG_a) && (!IS_NETSTAT_PROTO_FLAGS_UP) ) - toys.optflags |= FLAG_t | FLAG_u | FLAG_w | FLAG_x; - //when only l is set - if ( (toys.optflags & FLAG_l) && (!IS_NETSTAT_PROTO_FLAGS_UP) ) - toys.optflags |= FLAG_t | FLAG_u | FLAG_w | FLAG_x; - //when only e/n is set - if( ((toys.optflags & FLAG_e) || (toys.optflags & FLAG_n)) && (!IS_NETSTAT_PROTO_FLAGS_UP) ) - toys.optflags |= FLAG_t | FLAG_u | FLAG_w | FLAG_x; - //when W is set - if ( (toys.optflags & FLAG_W) && (!IS_NETSTAT_PROTO_FLAGS_UP) ) - toys.optflags |= FLAG_t | FLAG_u | FLAG_w | FLAG_x; - //when p is set - if ( (toys.optflags & FLAG_p) && (!IS_NETSTAT_PROTO_FLAGS_UP) ) + // For both 'a' and 'l' are set, remove 'l' option + if (toys.optflags & FLAG_a && toys.optflags & FLAG_l) + toys.optflags &= ~FLAG_l; + + // For each 'a', 'l', 'e', 'n', 'W', 'p' options + // without any 't', 'u', 'w', 'x' option, add 't', 'u', 'w', 'x' options + if (((toys.optflags & FLAG_a) || (toys.optflags & FLAG_l) || + (toys.optflags & FLAG_e) || (toys.optflags & FLAG_n) || + (toys.optflags & FLAG_W) || (toys.optflags & FLAG_p)) && + (!IS_NETSTAT_PROTO_FLAGS_UP) ) toys.optflags |= FLAG_t | FLAG_u | FLAG_w | FLAG_x; //Display routing table. @@ -581,12 +619,13 @@ void netstat_main(void) } //For TCP/UDP/RAW. - if ( (toys.optflags & FLAG_t) || (toys.optflags & FLAG_u) || (toys.optflags & FLAG_w) ) { + if ( (toys.optflags & FLAG_t) || (toys.optflags & FLAG_u) || + (toys.optflags & FLAG_w) ) { xprintf("Active Internet connections "); - if (flag_listen_and_all) xprintf("(servers and established)"); - else if (toys.optflags & FLAG_l) xprintf("(only servers)"); - else xprintf("(w/o servers)"); + if (toys.optflags & FLAG_a) xprintf("(servers and established)\n"); + else if (toys.optflags & FLAG_l) xprintf("(only servers)\n"); + else xprintf("(w/o servers)\n"); show_header(); if (toys.optflags & FLAG_t) {//For TCP @@ -602,14 +641,18 @@ void netstat_main(void) show_ipv6("/proc/net/raw6", "raw"); } } - if (toys.optflags & FLAG_x) {//For UNIX. + if (toys.optflags & FLAG_x) {//For UNIX xprintf("Active UNIX domain sockets "); - if (flag_listen_and_all) xprintf("(servers and established)"); - else if (toys.optflags & FLAG_l) xprintf("(only servers)"); - else xprintf("(w/o servers)"); - - if (toys.optflags & FLAG_p) xprintf("\nProto RefCnt Flags Type State I-Node PID/Program Name Path\n"); - else xprintf("\nProto RefCnt Flags Type State I-Node Path\n"); + if (toys.optflags & FLAG_a) xprintf("(servers and established)\n"); + else if (toys.optflags & FLAG_l) xprintf("(only servers)\n"); + else xprintf("(w/o servers)\n"); + + if (toys.optflags & FLAG_p) + xprintf("Proto RefCnt Flags Type State " + "I-Node PID/Program Name Path\n"); + else + xprintf("Proto RefCnt Flags Type State " + "I-Node Path\n"); show_unix_sockets("/proc/net/unix", "unix"); } if (toys.optflags & FLAG_p) clean_pid_list(); |