1 /* 2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * James Woodcock 8 */ 9 10 #include <arpa/inet.h> 11 #include <errno.h> 12 #include <getopt.h> 13 #include <net/if.h> 14 #include <netdb.h> 15 #include <netinet/in.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 #include <SupportDefs.h> 22 23 #include <net_stat.h> 24 #include <syscalls.h> 25 26 27 extern const char* __progname; 28 const char* kProgramName = __progname; 29 30 static int sResolveNames = 1; 31 32 struct address_family { 33 int family; 34 const char* name; 35 const char* identifiers[4]; 36 void (*print_address)(sockaddr* address); 37 }; 38 39 // AF_INET family 40 static void inet_print_address(sockaddr* address); 41 42 static const address_family kFamilies[] = { 43 { 44 AF_INET, 45 "inet", 46 {"AF_INET", "inet", "ipv4", NULL}, 47 inet_print_address 48 }, 49 { -1, NULL, {NULL}, NULL } 50 }; 51 52 53 static void 54 inet_print_address(sockaddr* _address) 55 { 56 sockaddr_in& address = *(sockaddr_in *)_address; 57 58 if (address.sin_family != AF_INET || address.sin_len == 0) { 59 printf("%-22s", "-"); 60 return; 61 } 62 63 hostent* host = NULL; 64 servent* service = NULL; 65 if (sResolveNames) { 66 host = gethostbyaddr((const char*)&address.sin_addr, sizeof(in_addr), 67 AF_INET); 68 service = getservbyport(address.sin_port, NULL); 69 } 70 71 const char *hostName; 72 if (host != NULL) 73 hostName = host->h_name; 74 else if (address.sin_addr.s_addr == INADDR_ANY) 75 hostName = "*"; 76 else 77 hostName = inet_ntoa(address.sin_addr); 78 79 char buffer[128]; 80 int length = strlcpy(buffer, hostName, sizeof(buffer)); 81 82 char port[64]; 83 if (service != NULL) 84 strlcpy(port, service->s_name, sizeof(port)); 85 else if (address.sin_port == 0) 86 strcpy(port, "*"); 87 else 88 snprintf(port, sizeof(port), "%u", ntohs(address.sin_port)); 89 90 snprintf(buffer + length, sizeof(buffer) - length, ":%s", port); 91 92 printf("%-22s", buffer); 93 } 94 95 96 // #pragma mark - 97 98 99 void 100 usage(int status) 101 { 102 printf("usage: %s [-nh]\n", kProgramName); 103 printf("options:\n"); 104 printf(" -n don't resolve names\n"); 105 printf(" -h this help\n"); 106 107 exit(status); 108 } 109 110 111 bool 112 get_address_family(const char* argument, int32& familyIndex) 113 { 114 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 115 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 116 if (!strcmp(argument, kFamilies[i].identifiers[j])) { 117 // found a match 118 familyIndex = i; 119 return true; 120 } 121 } 122 } 123 124 // defaults to AF_INET 125 familyIndex = 0; 126 return false; 127 } 128 129 130 // #pragma mark - 131 132 133 int 134 main(int argc, char** argv) 135 { 136 int optionIndex = 0; 137 int opt; 138 static struct option longOptions[] = { 139 {"help", no_argument, 0, 'h'}, 140 {"numeric", no_argument, 0, 'n'}, 141 {0, 0, 0, 0} 142 }; 143 144 do { 145 opt = getopt_long(argc, argv, "hn", longOptions, &optionIndex); 146 switch (opt) { 147 case -1: 148 // end of arguments, do nothing 149 break; 150 151 case 'n': 152 sResolveNames = 0; 153 break; 154 155 case 'h': 156 default: 157 usage(0); 158 break; 159 } 160 } while (opt != -1); 161 162 bool printProgram = true; 163 // TODO: add some more program options... :-) 164 165 printf("Proto Recv-Q Send-Q Local Address Foreign Address " 166 "State Program\n"); 167 168 uint32 cookie = 0; 169 int family = -1; 170 net_stat stat; 171 while (_kern_get_next_socket_stat(family, &cookie, &stat) == B_OK) { 172 protoent* proto = getprotobynumber(stat.protocol); 173 if (proto != NULL) 174 printf("%-6s ", proto->p_name); 175 else 176 printf("%-6d ", stat.protocol); 177 178 printf("%6lu ", stat.receive_queue_size); 179 printf("%6lu ", stat.send_queue_size); 180 181 inet_print_address((sockaddr*)&stat.address); 182 inet_print_address((sockaddr*)&stat.peer); 183 printf("%-12s ", stat.state); 184 185 team_info info; 186 if (printProgram && get_team_info(stat.owner, &info) == B_OK) { 187 // remove arguments 188 char* name = strchr(info.args, ' '); 189 if (name != NULL) 190 name[0] = '\0'; 191 192 // remove path name 193 name = strrchr(info.args, '/'); 194 if (name != NULL) 195 name++; 196 else 197 name = info.args; 198 199 printf("%ld/%s\n", stat.owner, name); 200 } else 201 printf("%ld\n", stat.owner); 202 } 203 204 return 0; 205 } 206 207