diff options
Diffstat (limited to 'package/toolbox/src/src/netstat.c')
-rw-r--r-- | package/toolbox/src/src/netstat.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/package/toolbox/src/src/netstat.c b/package/toolbox/src/src/netstat.c new file mode 100644 index 000000000..31365acd6 --- /dev/null +++ b/package/toolbox/src/src/netstat.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2008, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <arpa/inet.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> + +typedef union iaddr iaddr; +typedef union iaddr6 iaddr6; + +union iaddr { + unsigned u; + unsigned char b[4]; +}; + +union iaddr6 { + struct { + unsigned a; + unsigned b; + unsigned c; + unsigned d; + } u; + unsigned char b[16]; +}; + +static const char *state2str(unsigned state) +{ + switch(state){ + case 0x1: return "ESTABLISHED"; + case 0x2: return "SYN_SENT"; + case 0x3: return "SYN_RECV"; + case 0x4: return "FIN_WAIT1"; + case 0x5: return "FIN_WAIT2"; + case 0x6: return "TIME_WAIT"; + case 0x7: return "CLOSE"; + case 0x8: return "CLOSE_WAIT"; + case 0x9: return "LAST_ACK"; + case 0xA: return "LISTEN"; + case 0xB: return "CLOSING"; + default: return "UNKNOWN"; + } +} + +/* addr + : + port + \0 */ +#define ADDR_LEN INET6_ADDRSTRLEN + 1 + 5 + 1 + +static void addr2str(int af, const void *addr, unsigned port, char *buf) +{ + if (inet_ntop(af, addr, buf, ADDR_LEN) == NULL) { + *buf = '\0'; + return; + } + size_t len = strlen(buf); + if (port) { + snprintf(buf+len, ADDR_LEN-len, ":%d", port); + } else { + strncat(buf+len, ":*", ADDR_LEN-len-1); + } +} + +static void ipv4(const char *filename, const char *label) { + FILE *fp = fopen(filename, "r"); + if (fp == NULL) { + return; + } + char buf[BUFSIZ]; + fgets(buf, BUFSIZ, fp); + while (fgets(buf, BUFSIZ, fp)){ + char lip[ADDR_LEN]; + char rip[ADDR_LEN]; + iaddr laddr, raddr; + unsigned lport, rport, state, txq, rxq, num; + int n = sscanf(buf, " %d: %x:%x %x:%x %x %x:%x", + &num, &laddr.u, &lport, &raddr.u, &rport, + &state, &txq, &rxq); + if (n == 8) { + addr2str(AF_INET, &laddr, lport, lip); + addr2str(AF_INET, &raddr, rport, rip); + + printf("%4s %6d %6d %-22s %-22s %s\n", + label, rxq, txq, lip, rip, + state2str(state)); + } + } + fclose(fp); +} + +static void ipv6(const char *filename, const char *label) { + FILE *fp = fopen(filename, "r"); + if (fp == NULL) { + return; + } + char buf[BUFSIZ]; + fgets(buf, BUFSIZ, fp); + while (fgets(buf, BUFSIZ, fp)){ + char lip[ADDR_LEN]; + char rip[ADDR_LEN]; + iaddr6 laddr6, raddr6; + unsigned lport, rport, state, txq, rxq, num; + int n = sscanf(buf, " %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x", + &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); + if (n == 14) { + addr2str(AF_INET6, &laddr6, lport, lip); + addr2str(AF_INET6, &raddr6, rport, rip); + + printf("%4s %6d %6d %-22s %-22s %s\n", + label, rxq, txq, lip, rip, + state2str(state)); + } + } + fclose(fp); +} + +int main(int argc, char *argv[]) +{ + printf("Proto Recv-Q Send-Q Local Address Foreign Address State\n"); + ipv4("/proc/net/tcp", "tcp"); + ipv4("/proc/net/udp", "udp"); + ipv6("/proc/net/tcp6", "tcp6"); + ipv6("/proc/net/udp6", "udp6"); + return 0; +} |