1 /* 2 * Copyright (c) 2008, The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google, Inc. nor the names of its contributors 15 * may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <arpa/inet.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <sys/socket.h> 36 #include <sys/types.h> 37 38 typedef union iaddr iaddr; 39 typedef union iaddr6 iaddr6; 40 41 union iaddr { 42 unsigned u; 43 unsigned char b[4]; 44 }; 45 46 union iaddr6 { 47 struct { 48 unsigned a; 49 unsigned b; 50 unsigned c; 51 unsigned d; 52 } u; 53 unsigned char b[16]; 54 }; 55 56 static const char *state2str(unsigned state) 57 { 58 switch(state){ 59 case 0x1: return "ESTABLISHED"; 60 case 0x2: return "SYN_SENT"; 61 case 0x3: return "SYN_RECV"; 62 case 0x4: return "FIN_WAIT1"; 63 case 0x5: return "FIN_WAIT2"; 64 case 0x6: return "TIME_WAIT"; 65 case 0x7: return "CLOSE"; 66 case 0x8: return "CLOSE_WAIT"; 67 case 0x9: return "LAST_ACK"; 68 case 0xA: return "LISTEN"; 69 case 0xB: return "CLOSING"; 70 default: return "UNKNOWN"; 71 } 72 } 73 74 /* addr + : + port + \0 */ 75 #define ADDR_LEN INET6_ADDRSTRLEN + 1 + 5 + 1 76 77 static void addr2str(int af, const void *addr, unsigned port, char *buf) 78 { 79 if (inet_ntop(af, addr, buf, ADDR_LEN) == NULL) { 80 *buf = '\0'; 81 return; 82 } 83 size_t len = strlen(buf); 84 if (port) { 85 snprintf(buf+len, ADDR_LEN-len, ":%d", port); 86 } else { 87 strncat(buf+len, ":*", ADDR_LEN-len-1); 88 } 89 } 90 91 static void ipv4(const char *filename, const char *label) { 92 FILE *fp = fopen(filename, "r"); 93 if (fp == NULL) { 94 return; 95 } 96 char buf[BUFSIZ]; 97 fgets(buf, BUFSIZ, fp); 98 while (fgets(buf, BUFSIZ, fp)){ 99 char lip[ADDR_LEN]; 100 char rip[ADDR_LEN]; 101 iaddr laddr, raddr; 102 unsigned lport, rport, state, txq, rxq, num; 103 int n = sscanf(buf, " %d: %x:%x %x:%x %x %x:%x", 104 &num, &laddr.u, &lport, &raddr.u, &rport, 105 &state, &txq, &rxq); 106 if (n == 8) { 107 addr2str(AF_INET, &laddr, lport, lip); 108 addr2str(AF_INET, &raddr, rport, rip); 109 110 printf("%4s %6d %6d %-22s %-22s %s\n", 111 label, rxq, txq, lip, rip, 112 state2str(state)); 113 } 114 } 115 fclose(fp); 116 } 117 118 static void ipv6(const char *filename, const char *label) { 119 FILE *fp = fopen(filename, "r"); 120 if (fp == NULL) { 121 return; 122 } 123 char buf[BUFSIZ]; 124 fgets(buf, BUFSIZ, fp); 125 while (fgets(buf, BUFSIZ, fp)){ 126 char lip[ADDR_LEN]; 127 char rip[ADDR_LEN]; 128 iaddr6 laddr6, raddr6; 129 unsigned lport, rport, state, txq, rxq, num; 130 int n = sscanf(buf, " %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x", 131 &num, &laddr6.u.a, &laddr6.u.b, &laddr6.u.c, &laddr6.u.d, &lport, 132 &raddr6.u.a, &raddr6.u.b, &raddr6.u.c, &raddr6.u.d, &rport, 133 &state, &txq, &rxq); 134 if (n == 14) { 135 addr2str(AF_INET6, &laddr6, lport, lip); 136 addr2str(AF_INET6, &raddr6, rport, rip); 137 138 printf("%4s %6d %6d %-22s %-22s %s\n", 139 label, rxq, txq, lip, rip, 140 state2str(state)); 141 } 142 } 143 fclose(fp); 144 } 145 146 int netstat_main(int argc, char *argv[]) 147 { 148 printf("Proto Recv-Q Send-Q Local Address Foreign Address State\n"); 149 ipv4("/proc/net/tcp", "tcp"); 150 ipv4("/proc/net/udp", "udp"); 151 ipv6("/proc/net/tcp6", "tcp6"); 152 ipv6("/proc/net/udp6", "udp6"); 153 return 0; 154 } 155